home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / PARSE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-15  |  122.1 KB  |  5,867 lines  |  [TEXT/CWIE]

  1. /****************************************************************************
  2. *                parse.c
  3. *
  4. *  This module implements a parser for the scene description files.
  5. *
  6. *  from Persistence of Vision(tm) Ray Tracer
  7. *  Copyright 1996 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23.  
  24. #include "frame.h"
  25. #include "vector.h"
  26. #include "povproto.h"
  27. #include "parse.h"
  28. #include "parstxtr.h"
  29. #include "atmosph.h"
  30. #include "bezier.h"   
  31. #include "blob.h"     
  32. #include "boxes.h"
  33. #include "colour.h"
  34. #include "cones.h"    
  35. #include "csg.h"      
  36. #include "discs.h"
  37. #include "express.h"  
  38. #include "fractal.h"
  39. #include "gif.h"      
  40. #include "halos.h"
  41. #include "hfield.h"
  42. #include "iff.h"      
  43. #include "image.h"    
  44. #include "lathe.h"    
  45. #include "polysolv.h"
  46. #include "matrices.h"
  47. #include "mesh.h"
  48. #include "normal.h"
  49. #include "objects.h"
  50. #include "octree.h"
  51. #include "pigment.h"
  52. #include "planes.h"
  53. #include "poly.h"
  54. #include "polygon.h"
  55. #include "povray.h"   
  56. #include "pgm.h"      
  57. #include "ppm.h"      
  58. #include "prism.h"    
  59. #include "quadrics.h" 
  60. #include "radiosit.h"      
  61. #include "render.h"   
  62. #include "sor.h"      
  63. #include "spheres.h"  
  64. #include "super.h"
  65. #include "targa.h"    
  66. #include "texture.h"  
  67. #include "tokenize.h" 
  68. #include "torus.h"
  69. #include "triangle.h" 
  70. #include "truetype.h" 
  71.  
  72.  
  73. /*****************************************************************************
  74. * Local preprocessor defines
  75. ******************************************************************************/
  76.  
  77. /* Volume that is considered to be infinite. [DB 9/94] */
  78.  
  79. #define INFINITE_VOLUME BOUND_HUGE
  80.  
  81.  
  82. /*****************************************************************************
  83. * Local typedefs
  84. ******************************************************************************/
  85.  
  86.  
  87.  
  88. /*****************************************************************************
  89. * Local variables
  90. ******************************************************************************/
  91.  
  92. short Have_Vector;
  93. short Not_In_Default;
  94. short Ok_To_Declare;
  95.  
  96. static TOKEN *Brace_Stack;
  97. static int Brace_Index;
  98. static CAMERA *Default_Camera;
  99.  
  100.  
  101.  
  102. /*****************************************************************************
  103. * Static functions
  104. ******************************************************************************/
  105.  
  106. static TRANSFORM *Parse_Transform PARAMS((void));
  107. static void Frame_Init PARAMS((void));
  108. static void Parse_Coeffs PARAMS((int order, DBL *Coeffs));
  109.  
  110. static OBJECT *Parse_Bicubic_Patch PARAMS((void));
  111. static OBJECT *Parse_Blob PARAMS((void));
  112. static OBJECT *Parse_Bound_Clip PARAMS((void));
  113. static OBJECT *Parse_Box PARAMS((void));
  114. static OBJECT *Parse_Cone PARAMS((void));
  115. static OBJECT *Parse_CSG PARAMS((int CSG_Type));
  116. static OBJECT *Parse_Cylinder PARAMS((void));
  117. static OBJECT *Parse_Disc PARAMS((void));
  118. static OBJECT *Parse_Julia_Fractal PARAMS((void));
  119. static OBJECT *Parse_HField PARAMS((void));
  120. static OBJECT *Parse_Lathe PARAMS((void));
  121. static OBJECT *Parse_Light_Source PARAMS((void));
  122. static OBJECT *Parse_Object_Id PARAMS((void));
  123. static OBJECT *Parse_Plane PARAMS((void));
  124. static OBJECT *Parse_Poly PARAMS((int order));
  125. static OBJECT *Parse_Polygon PARAMS((void));
  126. static OBJECT *Parse_Prism PARAMS((void));
  127. static OBJECT *Parse_Quadric PARAMS((void));
  128. static OBJECT *Parse_Smooth_Triangle PARAMS((void));
  129. static OBJECT *Parse_Sor PARAMS((void));
  130. static OBJECT *Parse_Sphere PARAMS((void));
  131. static OBJECT *Parse_Superellipsoid PARAMS((void));
  132. static OBJECT *Parse_Torus PARAMS((void));
  133. static OBJECT *Parse_Triangle PARAMS((void));
  134. static OBJECT *Parse_Mesh PARAMS((void));
  135. static TEXTURE *Parse_Mesh_Texture PARAMS((void));
  136. static OBJECT *Parse_TrueType PARAMS((void));
  137. static void Parse_Blob_Element_Mods PARAMS((BLOB_ELEMENT *Element));
  138.  
  139. static void Parse_Camera PARAMS((CAMERA **Camera_Ptr));
  140. static void Parse_Frame PARAMS((void));
  141.  
  142. static char *Get_Token_String PARAMS((TOKEN Token_Id));
  143. static int Test_Redefine PARAMS((int Previous, int a));
  144. static void Destroy_Constants PARAMS((void));
  145. static void Found_Instead PARAMS((void));
  146. static void Link PARAMS((OBJECT *New_Object,OBJECT **Field,OBJECT **Old_Object_List));
  147. static void Link_To_Frame PARAMS((OBJECT *Object));
  148. static void Post_Process PARAMS((OBJECT *Object, OBJECT *Parent));
  149. static void Parse_Global_Settings PARAMS((void));
  150. static void Global_Setting_Warn PARAMS((void));
  151.  
  152. static void Set_CSG_Children_Hollow PARAMS((OBJECT *Object, int hollow));
  153.  
  154.  
  155.  
  156. /*****************************************************************************
  157. *
  158. * FUNCTION
  159. *
  160. * INPUT
  161. *
  162. * OUTPUT
  163. *
  164. * RETURNS
  165. *
  166. * AUTHOR
  167. *   
  168. * DESCRIPTION
  169. *
  170. * CHANGES
  171. *
  172. ******************************************************************************/
  173.  
  174. /* Parse the file. */
  175. void Parse ()
  176. {
  177.   Initialize_Tokenizer();
  178.   Brace_Stack = (TOKEN *)POV_MALLOC(MAX_BRACES*sizeof (TOKEN), "brace stack");
  179.   Brace_Index = 0;
  180.  
  181.   Default_Camera = Create_Camera();
  182.  
  183.   Default_Texture = Create_Texture();
  184.  
  185.   Default_Texture->Pigment = Create_Pigment();
  186.   Default_Texture->Tnormal = NULL;
  187.   Default_Texture->Finish  = Create_Finish();
  188.   Default_Texture->Halo    = NULL;
  189.  
  190.   Not_In_Default = TRUE;
  191.   Ok_To_Declare = TRUE;
  192.  
  193.   Frame_Init ();
  194.   
  195.   Stage = STAGE_PARSING;
  196.  
  197.   Parse_Frame ();
  198.  
  199.   if (Frame.Objects == NULL)
  200.   {
  201.     Error ("No objects in scene.");
  202.   }
  203.      
  204.   Stage = STAGE_CLEANUP_PARSE;
  205.  
  206.   Terminate_Tokenizer();
  207.   Destroy_Constants ();
  208.   Destroy_Textures(Default_Texture); 
  209.   Destroy_Camera(Default_Camera); 
  210.   POV_FREE (Brace_Stack);
  211.  
  212.   Default_Texture = NULL;
  213.   Default_Camera = NULL;
  214.   Brace_Stack = NULL;
  215. }
  216.  
  217.  
  218.  
  219. /*****************************************************************************
  220. *
  221. * FUNCTION
  222. *
  223. * INPUT
  224. *   
  225. * OUTPUT
  226. *   
  227. * RETURNS
  228. *   
  229. * AUTHOR
  230. *   
  231. * DESCRIPTION
  232. *
  233. * CHANGES
  234. *
  235. ******************************************************************************/
  236.  
  237. /* Set up the fields in the frame to default values. */
  238. static
  239. void Frame_Init ()
  240.   {
  241.    Frame.Camera = Copy_Camera(Default_Camera);
  242.    Frame.Number_Of_Light_Sources = 0;  
  243.    Frame.Light_Sources = NULL;
  244.    Frame.Objects = NULL;
  245.    Frame.Atmosphere_IOR = 1.0;
  246.    Frame.Antialias_Threshold = opts.Antialias_Threshold;
  247.  
  248. /* dmf -- the first is physically "more correct".  The second works better */
  249. /*   Make_Colour (Frame.Irid_Wavelengths, 0.70, 0.52, 0.48); */
  250.    Make_Colour (Frame.Irid_Wavelengths, 0.25, 0.18, 0.14);
  251.    Make_Colour (Frame.Background_Colour, 0.0, 0.0, 0.0);
  252.    Make_Colour (Frame.Ambient_Light, 1.0, 1.0, 1.0);
  253.  
  254.    /* Init atmospheric stuff. [DB 12/94] */
  255.  
  256.    Frame.Atmosphere = NULL;
  257.  
  258.    Frame.Fog = NULL;
  259.  
  260.    Frame.Rainbow = NULL;
  261.  
  262.    Frame.Skysphere = NULL;
  263.   }
  264.  
  265.  
  266.  
  267. /*****************************************************************************
  268. *
  269. * FUNCTION
  270. *
  271. * INPUT
  272. *   
  273. * OUTPUT
  274. *   
  275. * RETURNS
  276. *   
  277. * AUTHOR
  278. *   
  279. * DESCRIPTION
  280. *
  281. * CHANGES
  282. *
  283. ******************************************************************************/
  284.  
  285. void Parse_Begin ()
  286.   {
  287.    char *front;
  288.  
  289.    Brace_Stack[++Brace_Index]=Token.Token_Id;
  290.  
  291.    Get_Token ();
  292.  
  293.    if (Token.Token_Id == LEFT_CURLY_TOKEN)
  294.      return;
  295.  
  296.    front = Get_Token_String (Brace_Stack[Brace_Index]);
  297.  
  298.    Where_Error ();
  299.    Error_Line ("Missing { after %s, ", front);
  300.    Found_Instead ();
  301.   }
  302.  
  303.  
  304.  
  305. /*****************************************************************************
  306. *
  307. * FUNCTION
  308. *
  309. * INPUT
  310. *   
  311. * OUTPUT
  312. *   
  313. * RETURNS
  314. *   
  315. * AUTHOR
  316. *   
  317. * DESCRIPTION
  318. *
  319. * CHANGES
  320. *
  321. ******************************************************************************/
  322.  
  323. void Parse_End ()
  324.   {
  325.    char *front;
  326.  
  327.    Get_Token ();
  328.  
  329.    if (Token.Token_Id == RIGHT_CURLY_TOKEN)
  330.      {
  331.       Brace_Index--;
  332.       return;
  333.      }
  334.  
  335.    front = Get_Token_String (Brace_Stack[Brace_Index]);
  336.  
  337.    Where_Error ();
  338.    Error_Line("No matching } in %s,", front);
  339.    Found_Instead ();
  340.   }
  341.  
  342.  
  343.  
  344. /*****************************************************************************
  345. *
  346. * FUNCTION
  347. *
  348. * INPUT
  349. *   
  350. * OUTPUT
  351. *   
  352. * RETURNS
  353. *   
  354. * AUTHOR
  355. *   
  356. * DESCRIPTION
  357. *
  358. * CHANGES
  359. *
  360. ******************************************************************************/
  361.  
  362. static OBJECT *Parse_Object_Id ()
  363.   {
  364.    OBJECT *Object;
  365.  
  366.    EXPECT
  367.      CASE (OBJECT_ID_TOKEN)
  368.        Warn_State(OBJECT_ID_TOKEN, OBJECT_TOKEN);
  369.        Object = Copy_Object((OBJECT *) Token.Constant_Data);
  370.        Parse_Object_Mods (Object);
  371.        EXIT
  372.      END_CASE
  373.  
  374.      OTHERWISE
  375.        Object = NULL;
  376.        UNGET
  377.        EXIT
  378.      END_CASE
  379.    END_EXPECT
  380.  
  381.    return (Object);
  382.   }
  383.  
  384.  
  385.  
  386. /*****************************************************************************
  387. *
  388. * FUNCTION
  389. *
  390. * INPUT
  391. *   
  392. * OUTPUT
  393. *   
  394. * RETURNS
  395. *   
  396. * AUTHOR
  397. *   
  398. * DESCRIPTION
  399. *
  400. * CHANGES
  401. *
  402. ******************************************************************************/
  403.  
  404. void Parse_Comma ()
  405.   {
  406.    Get_Token();
  407.    if (Token.Token_Id != COMMA_TOKEN)
  408.      {
  409.       UNGET;
  410.      }
  411.   }
  412.  
  413.  
  414.  
  415. /*****************************************************************************
  416. *
  417. * FUNCTION
  418. *
  419. * INPUT
  420. *   
  421. * OUTPUT
  422. *   
  423. * RETURNS
  424. *   
  425. * AUTHOR
  426. *   
  427. * DESCRIPTION
  428. *
  429. * CHANGES
  430. *
  431. ******************************************************************************/
  432.  
  433. static void Parse_Coeffs(order, Coeffs)
  434.   int order;
  435.   DBL *Coeffs;
  436.   {
  437.    int i;
  438.  
  439.    EXPECT
  440.      CASE (LEFT_ANGLE_TOKEN)
  441.        Coeffs[0] = Parse_Float();
  442.        for (i = 1; i < term_counts(order); i++)
  443.          {
  444.           Parse_Comma();
  445.           Coeffs[i] = Parse_Float();
  446.          }
  447.        GET (RIGHT_ANGLE_TOKEN);
  448.        EXIT
  449.      END_CASE
  450.  
  451.      OTHERWISE
  452.        Parse_Error (LEFT_ANGLE_TOKEN);
  453.      END_CASE
  454.    END_EXPECT
  455.   }
  456.  
  457.  
  458.  
  459. /*****************************************************************************
  460. *
  461. * FUNCTION
  462. *
  463. * INPUT
  464. *
  465. * OUTPUT
  466. *
  467. * RETURNS
  468. *
  469. * AUTHOR
  470. *
  471. * DESCRIPTION
  472. *
  473. * CHANGES
  474. *
  475. ******************************************************************************/
  476.  
  477. static
  478. OBJECT *Parse_Bound_Clip ()
  479.   {
  480.    VECTOR Local_Vector;
  481.    MATRIX Local_Matrix;
  482.    TRANSFORM Local_Trans;
  483.    OBJECT *First, *Current, *Prev;
  484.  
  485.    First = Prev = NULL;
  486.  
  487.    while ((Current = Parse_Object ()) != NULL)
  488.      {
  489.       if (Current->Type & (TEXTURED_OBJECT+PATCH_OBJECT))
  490.         Error ("Illegal texture or patch in clip or bound.");
  491.       if (First == NULL)
  492.         First = Current;
  493.       if (Prev != NULL)
  494.         Prev->Sibling = Current;
  495.       Prev = Current;
  496.      }
  497.  
  498.    EXPECT
  499.      CASE (TRANSLATE_TOKEN)
  500.        Parse_Vector (Local_Vector);
  501.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  502.        for (Current = First; Current != NULL; Current = Current->Sibling)
  503.        {
  504.          Translate_Object (Current, Local_Vector, &Local_Trans);
  505.        }
  506.      END_CASE
  507.  
  508.      CASE (ROTATE_TOKEN)
  509.        Parse_Vector (Local_Vector);
  510.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  511.        for (Current = First; Current != NULL; Current = Current->Sibling)
  512.        {
  513.          Rotate_Object (Current, Local_Vector, &Local_Trans);
  514.        }
  515.      END_CASE
  516.  
  517.      CASE (SCALE_TOKEN)
  518.        Parse_Scale_Vector (Local_Vector);
  519.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  520.        for (Current = First; Current != NULL; Current = Current->Sibling)
  521.        {
  522.          Scale_Object (Current, Local_Vector, &Local_Trans);
  523.        }
  524.      END_CASE
  525.  
  526.      CASE (TRANSFORM_TOKEN)
  527.        GET(TRANSFORM_ID_TOKEN)
  528.        for (Current = First; Current != NULL; Current = Current->Sibling)
  529.        {
  530.          Transform_Object (Current, (TRANSFORM *)Token.Constant_Data);
  531.        }
  532.      END_CASE
  533.  
  534.      CASE (MATRIX_TOKEN)
  535.        Parse_Matrix (Local_Matrix);
  536.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  537.        for (Current = First; Current != NULL; Current = Current->Sibling)
  538.        {
  539.          Transform_Object (Current, &Local_Trans);
  540.        }
  541.      END_CASE
  542.  
  543.      OTHERWISE
  544.        UNGET
  545.        EXIT
  546.      END_CASE
  547.    END_EXPECT
  548.  
  549.    if (First==NULL)
  550.    {
  551.       Parse_Error_Str("object");
  552.    }
  553.  
  554.    return (First);
  555.   }
  556.  
  557.  
  558.  
  559. /*****************************************************************************
  560. *
  561. * FUNCTION
  562. *
  563. * INPUT
  564. *   
  565. * OUTPUT
  566. *   
  567. * RETURNS
  568. *   
  569. * AUTHOR
  570. *   
  571. * DESCRIPTION
  572. *
  573. * CHANGES
  574. *
  575. ******************************************************************************/
  576.  
  577. void Parse_Object_Mods (Object)
  578.   OBJECT *Object;
  579.   {
  580.    DBL Temp_Water_Level;
  581.    DBL V1, V2;
  582.    VECTOR Min, Max;  
  583.    VECTOR Local_Vector;
  584.    MATRIX Local_Matrix;
  585.    TRANSFORM Local_Trans;
  586.    BBOX BBox;
  587.    OBJECT *Sib;
  588.    TEXTURE *Local_Texture;
  589.    OBJECT *Temp1_Object;
  590.    OBJECT *Temp2_Object;
  591.    COLOUR Local_Colour;
  592.  
  593.    EXPECT
  594.      CASE_COLOUR
  595.        Parse_Colour (Local_Colour);
  596.        if (opts.Language_Version < 1.5)
  597.          if (Object->Texture != NULL)
  598.            if (Object->Texture->Type == PLAIN_PATTERN)
  599.              if (opts.Quality_Flags & Q_QUICKC)
  600.              {
  601.               Assign_Colour(Object->Texture->Pigment->Colour,Local_Colour);
  602.               break;  /* acts like END_CASE */
  603.              }
  604.        Warn(0.0, "Quick color belongs in texture. Color ignored.");
  605.      END_CASE
  606.  
  607.      CASE (TRANSLATE_TOKEN)
  608.        Parse_Vector (Local_Vector);
  609.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  610.        Translate_Object (Object, Local_Vector, &Local_Trans);
  611.      END_CASE
  612.  
  613.      CASE (ROTATE_TOKEN)
  614.        Parse_Vector (Local_Vector);
  615.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  616.        Rotate_Object (Object, Local_Vector, &Local_Trans);
  617.      END_CASE
  618.  
  619.      CASE (SCALE_TOKEN)
  620.        Parse_Scale_Vector (Local_Vector);
  621.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  622.        Scale_Object (Object, Local_Vector, &Local_Trans);
  623.      END_CASE
  624.  
  625.      CASE (TRANSFORM_TOKEN)
  626.        GET(TRANSFORM_ID_TOKEN)
  627.        Transform_Object (Object, (TRANSFORM *)Token.Constant_Data);
  628.      END_CASE
  629.  
  630.      CASE (MATRIX_TOKEN)
  631.        Parse_Matrix (Local_Matrix);
  632.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  633.        Transform_Object (Object, &Local_Trans);
  634.      END_CASE
  635.  
  636.      CASE (BOUNDED_BY_TOKEN)
  637.        Parse_Begin ();
  638.        if (Object->Bound != NULL)
  639.          if (Object->Clip == Object->Bound)
  640.            Error ("Cannot add bounds after linking bounds and clips.");
  641.  
  642.        EXPECT
  643.          CASE (CLIPPED_BY_TOKEN)
  644.            if (Object->Bound != NULL)
  645.              Error ("Cannot link clips with previous bounds.");
  646.            Object->Bound = Object->Clip;
  647.            EXIT
  648.          END_CASE
  649.  
  650.          OTHERWISE
  651.            UNGET
  652.            Temp1_Object = Temp2_Object = Parse_Bound_Clip ();
  653.            while (Temp2_Object->Sibling != NULL)
  654.              Temp2_Object = Temp2_Object->Sibling;
  655.            Temp2_Object->Sibling = Object->Bound;
  656.            Object->Bound = Temp1_Object;
  657.            EXIT
  658.          END_CASE
  659.        END_EXPECT
  660.  
  661.        Parse_End ();
  662.      END_CASE
  663.  
  664.      CASE (CLIPPED_BY_TOKEN)
  665.        Parse_Begin ();
  666.        if (Object->Clip != NULL)
  667.          if (Object->Clip == Object->Bound)
  668.            Error ("Cannot add clips after linking bounds and clips.");
  669.  
  670.        EXPECT
  671.          CASE (BOUNDED_BY_TOKEN)
  672.            if (Object->Clip != NULL)
  673.              Error ("Cannot link bounds with previous clips.");
  674.            Object->Clip = Object->Bound;
  675.            EXIT
  676.          END_CASE
  677.  
  678.          OTHERWISE
  679.            UNGET
  680.            Temp1_Object = Temp2_Object = Parse_Bound_Clip ();
  681.            while (Temp2_Object->Sibling != NULL)
  682.              Temp2_Object = Temp2_Object->Sibling;
  683.            Temp2_Object->Sibling = Object->Clip;
  684.            Object->Clip = Temp1_Object;
  685.  
  686.            /* Compute quadric bounding box before transformations. [DB 8/94] */
  687.  
  688.            if (Object->Methods == &Quadric_Methods)
  689.            {
  690.              Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  691.              Make_Vector(Max,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  692.  
  693.              Compute_Quadric_BBox((QUADRIC *)Object, Min, Max);
  694.            }
  695.            EXIT
  696.          END_CASE
  697.        END_EXPECT
  698.  
  699.        Parse_End ();
  700.      END_CASE
  701.  
  702.      CASE (TEXTURE_TOKEN)
  703.        Object->Type |= TEXTURED_OBJECT;
  704.        Parse_Begin ();
  705.        Local_Texture = Parse_Texture ();
  706.        Parse_End ();
  707.        Link_Textures(&(Object->Texture), Local_Texture);
  708.      END_CASE
  709.  
  710.      CASE4 (PIGMENT_TOKEN, TNORMAL_TOKEN, FINISH_TOKEN, HALO_TOKEN)
  711.        Object->Type |= TEXTURED_OBJECT;
  712.        if (Object->Texture == NULL)
  713.          Object->Texture = Copy_Textures(Default_Texture);
  714.        else
  715.          if (Object->Texture->Type != PLAIN_PATTERN)
  716.            Link_Textures(&(Object->Texture), Copy_Textures(Default_Texture));
  717.        UNGET
  718.        EXPECT
  719.          CASE (PIGMENT_TOKEN)
  720.            Parse_Begin ();
  721.            Parse_Pigment ( &(Object->Texture->Pigment) );
  722.            Parse_End ();
  723.          END_CASE
  724.  
  725.          CASE (TNORMAL_TOKEN)
  726.            Parse_Begin ();
  727.            Parse_Tnormal ( &(Object->Texture->Tnormal) );
  728.            Parse_End ();
  729.          END_CASE
  730.  
  731.          CASE (FINISH_TOKEN)
  732.            Parse_Finish ( &(Object->Texture->Finish) );
  733.          END_CASE
  734.  
  735.          CASE (HALO_TOKEN)
  736.            Parse_Halo ( &(Object->Texture->Halo) );
  737.          END_CASE
  738.  
  739.          OTHERWISE
  740.            UNGET
  741.            EXIT
  742.          END_CASE
  743.        END_EXPECT
  744.      END_CASE
  745.  
  746.      CASE (INVERSE_TOKEN)
  747.        if (Object->Type & PATCH_OBJECT)
  748.          Warn (0.0, "Cannot invert a patch object.");
  749.        Invert_Object (Object);
  750.      END_CASE
  751.  
  752.      CASE (STURM_TOKEN)
  753.        if (!(Object->Type & STURM_OK_OBJECT))
  754.          Not_With ("sturm","this object");
  755.        Bool_Flag (Object, STURM_FLAG, (Allow_Float(1.0) > 0.0));
  756.      END_CASE
  757.  
  758.      CASE (WATER_LEVEL_TOKEN)
  759.        if (!(Object->Type & WATER_LEVEL_OK_OBJECT))
  760.          Not_With ("water_level","this object");
  761.        Temp_Water_Level = Parse_Float();
  762.        if (opts.Language_Version < 2.0)
  763.          Temp_Water_Level /=256.0;
  764.        ((HFIELD *) Object)->bounding_box->bounds[0][Y] = 65536.0 * Temp_Water_Level;
  765.      END_CASE
  766.  
  767.      CASE (SMOOTH_TOKEN)
  768.        if (!(Object->Type & SMOOTH_OK_OBJECT))
  769.          Not_With ("smooth","this object");
  770.        Set_Flag(Object, SMOOTHED_FLAG);
  771.        Object->Type |= DOUBLE_ILLUMINATE;
  772.      END_CASE
  773.  
  774.      CASE (NO_SHADOW_TOKEN)
  775.        Set_Flag(Object, NO_SHADOW_FLAG);
  776.      END_CASE
  777.  
  778.      CASE (LIGHT_SOURCE_TOKEN)
  779.        Error("Light source must be defined using new syntax.");
  780.      END_CASE
  781.  
  782.      CASE(HIERARCHY_TOKEN)
  783.        if (!(Object->Type & HIERARCHY_OK_OBJECT))
  784.          Not_With ("hierarchy", "this object");
  785.        Bool_Flag (Object, HIERARCHY_FLAG, (Allow_Float(1.0) > 0.0));
  786.      END_CASE
  787.  
  788.      CASE(HOLLOW_TOKEN)
  789.        Bool_Flag (Object, HOLLOW_FLAG, (Allow_Float(1.0) > 0.0));
  790.        Set_Flag (Object, HOLLOW_SET_FLAG);
  791.        if ((Object->Methods == &CSG_Intersection_Methods) ||
  792.            (Object->Methods == &CSG_Merge_Methods) ||
  793.            (Object->Methods == &CSG_Union_Methods))
  794.        {
  795.          Set_CSG_Children_Hollow(Object, Test_Flag(Object, HOLLOW_FLAG));
  796.        }
  797.      END_CASE
  798.  
  799.      OTHERWISE
  800.        UNGET
  801.        EXIT
  802.      END_CASE
  803.    END_EXPECT
  804.  
  805.    /*
  806.     * Assign bounding objects' bounding box to object
  807.     * if object's bounding box is larger. [DB 9/94]
  808.     */
  809.  
  810.    if (Object->Bound != NULL)
  811.    {
  812.      /* Get bounding objects bounding box. */
  813.  
  814.      Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  815.      Make_Vector(Max,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  816.  
  817.      for (Sib = Object->Bound; Sib != NULL; Sib = Sib->Sibling)
  818.      {
  819.        if (!Test_Flag(Sib, INVERTED_FLAG))
  820.        {
  821.          Min[X] = max(Min[X], Sib->BBox.Lower_Left[X]);
  822.          Min[Y] = max(Min[Y], Sib->BBox.Lower_Left[Y]);
  823.          Min[Z] = max(Min[Z], Sib->BBox.Lower_Left[Z]);
  824.          Max[X] = min(Max[X], Sib->BBox.Lower_Left[X] + Sib->BBox.Lengths[X]);
  825.          Max[Y] = min(Max[Y], Sib->BBox.Lower_Left[Y] + Sib->BBox.Lengths[Y]);
  826.          Max[Z] = min(Max[Z], Sib->BBox.Lower_Left[Z] + Sib->BBox.Lengths[Z]);
  827.        }
  828.      }
  829.  
  830.      Make_BBox_from_min_max(BBox, Min, Max);
  831.  
  832.      /* Get bounding boxes' volumes. */
  833.  
  834.      BOUNDS_VOLUME(V1, BBox);
  835.      BOUNDS_VOLUME(V2, Object->BBox);
  836.  
  837.      if (V1 < V2)
  838.      {
  839.        Object->BBox = BBox;
  840.      }
  841.    }
  842.  
  843.    /*
  844.     * Assign clipping objects' bounding box to object
  845.     * if object's bounding box is larger. [DB 9/94]
  846.     */
  847.  
  848.    if (Object->Clip != NULL)
  849.    {
  850.      /* Get clipping objects bounding box. */
  851.  
  852.      Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  853.      Make_Vector(Max,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  854.  
  855.      for (Sib = Object->Clip; Sib != NULL; Sib = Sib->Sibling)
  856.      {
  857.        if (!Test_Flag(Sib, INVERTED_FLAG))
  858.        {
  859.          Min[X] = max(Min[X], Sib->BBox.Lower_Left[X]);
  860.          Min[Y] = max(Min[Y], Sib->BBox.Lower_Left[Y]);
  861.          Min[Z] = max(Min[Z], Sib->BBox.Lower_Left[Z]);
  862.          Max[X] = min(Max[X], Sib->BBox.Lower_Left[X] + Sib->BBox.Lengths[X]);
  863.          Max[Y] = min(Max[Y], Sib->BBox.Lower_Left[Y] + Sib->BBox.Lengths[Y]);
  864.          Max[Z] = min(Max[Z], Sib->BBox.Lower_Left[Z] + Sib->BBox.Lengths[Z]);
  865.        }
  866.      }
  867.  
  868.      Make_BBox_from_min_max(BBox, Min, Max);
  869.  
  870.      /* Get bounding boxes' volumes. */
  871.  
  872.      BOUNDS_VOLUME(V1, BBox);
  873.      BOUNDS_VOLUME(V2, Object->BBox);
  874.  
  875.      if (V1 < V2)
  876.      {
  877.        Object->BBox = BBox;
  878.      }
  879.    }
  880.  
  881.    Parse_End ();
  882.   }
  883.  
  884.  
  885.  
  886. /*****************************************************************************
  887. *
  888. * FUNCTION
  889. *
  890. *  Set_CSG_Children_Hollow
  891. *
  892. * INPUT
  893. *
  894. * OUTPUT
  895. *
  896. * RETURNS
  897. *
  898. * AUTHOR
  899. *
  900. * DESCRIPTION
  901. *
  902. * CHANGES
  903. *
  904. ******************************************************************************/
  905.  
  906. static void Set_CSG_Children_Hollow(Object, hollow)
  907. OBJECT *Object;
  908. int hollow;
  909. {
  910.   OBJECT *Sib;
  911.  
  912.   for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  913.   {
  914.     if (!Test_Flag(Sib, HOLLOW_SET_FLAG))
  915.     {
  916.       if ((Sib->Methods == &CSG_Intersection_Methods) ||
  917.           (Sib->Methods == &CSG_Merge_Methods) ||
  918.           (Sib->Methods == &CSG_Union_Methods))
  919.       {
  920.         Set_CSG_Children_Hollow(Sib, hollow);
  921.       }
  922.       else
  923.       {
  924.         Sib->Flags = (Sib->Flags & (~HOLLOW_FLAG)) | hollow;
  925.       }
  926.     }
  927.   }
  928. }
  929.  
  930.  
  931.  
  932. /*****************************************************************************
  933. *
  934. * FUNCTION
  935. *
  936. * INPUT
  937. *
  938. * OUTPUT
  939. *
  940. * RETURNS
  941. *
  942. * AUTHOR
  943. *
  944. * DESCRIPTION
  945. *
  946. * CHANGES
  947. *
  948. ******************************************************************************/
  949.  
  950. static OBJECT *Parse_Sphere()
  951. {
  952.   SPHERE *Object;
  953.  
  954.   Parse_Begin();
  955.  
  956.   if ((Object = (SPHERE *)Parse_Object_Id()) != NULL)
  957.   {
  958.     return ((OBJECT *) Object);
  959.   }
  960.  
  961.   Object = Create_Sphere();
  962.  
  963.   Parse_Vector(Object->Center);
  964.  
  965.   Parse_Comma();
  966.  
  967.   Object->Radius = Parse_Float();
  968.  
  969.   Compute_Sphere_BBox(Object);  
  970.  
  971.   Parse_Object_Mods((OBJECT *)Object);
  972.  
  973.   return((OBJECT *)Object);
  974. }
  975.  
  976.  
  977.  
  978. /*****************************************************************************
  979. *
  980. * FUNCTION
  981. *
  982. * INPUT
  983. *   
  984. * OUTPUT
  985. *   
  986. * RETURNS
  987. *   
  988. * AUTHOR
  989. *   
  990. * DESCRIPTION
  991. *
  992. * CHANGES
  993. *
  994. ******************************************************************************/
  995.  
  996. static
  997. OBJECT *Parse_Plane ()
  998.   {
  999.    DBL len;
  1000.    PLANE *Object;
  1001.  
  1002.    Parse_Begin ();
  1003.  
  1004.    if ( (Object = (PLANE *)Parse_Object_Id()) != NULL)
  1005.       return ((OBJECT *) Object);
  1006.  
  1007.    Object = Create_Plane();
  1008.  
  1009.    Parse_Vector(Object->Normal_Vector);   Parse_Comma();
  1010.    VLength(len, Object->Normal_Vector);
  1011.    if (len < EPSILON)
  1012.    {
  1013.      Error("Degenerate plane normal.");
  1014.    }
  1015.    VInverseScaleEq(Object->Normal_Vector, len);
  1016.    Object->Distance = -Parse_Float();
  1017.  
  1018.    Compute_Plane_BBox(Object);
  1019.  
  1020.    Parse_Object_Mods ((OBJECT *)Object);
  1021.  
  1022.    return ((OBJECT *) Object);
  1023.   }
  1024.  
  1025.  
  1026.  
  1027. /*****************************************************************************
  1028. *
  1029. * FUNCTION
  1030. *
  1031. * INPUT
  1032. *   
  1033. * OUTPUT
  1034. *   
  1035. * RETURNS
  1036. *   
  1037. * AUTHOR
  1038. *   
  1039. * DESCRIPTION
  1040. *
  1041. * CHANGES
  1042. *
  1043. ******************************************************************************/
  1044.  
  1045. static
  1046. OBJECT *Parse_HField ()
  1047. {
  1048.   HFIELD *Object;
  1049.   VECTOR Local_Vector;
  1050.   IMAGE *Image;
  1051.  
  1052.   Parse_Begin ();
  1053.  
  1054.   if ( (Object = (HFIELD *)Parse_Object_Id()) != NULL)
  1055.       return ((OBJECT *) Object);
  1056.  
  1057.    Object = Create_HField();
  1058.  
  1059.    Image = Parse_Image (HF_FILE);
  1060.    Image->Use_Colour_Flag = FALSE;
  1061.  
  1062.    Make_Vector(Object->bounding_box->bounds[0], 0.0, 0.0, 0.0);
  1063.  
  1064.    if (Image->File_Type == POT_FILE)
  1065.    {
  1066.      Object->bounding_box->bounds[1][X] = Image->width/2.0 - 1.0;
  1067.    }
  1068.    else
  1069.    {
  1070.      Object->bounding_box->bounds[1][X] = Image->width - 1.0;
  1071.    }
  1072.  
  1073.    Object->bounding_box->bounds[1][Y] = 65536.0;
  1074.    Object->bounding_box->bounds[1][Z] = Image->height - 1.0;
  1075.  
  1076.    Make_Vector(Local_Vector,
  1077.      1.0 / (Object->bounding_box->bounds[1][X]),
  1078.      1.0 / (Object->bounding_box->bounds[1][Y]),
  1079.      1.0 / (Object->bounding_box->bounds[1][Z]));
  1080.  
  1081.    Compute_Scaling_Transform(Object->Trans, Local_Vector);
  1082.  
  1083.    Parse_Object_Mods ((OBJECT *)Object);
  1084.  
  1085.    Compute_HField(Object, Image);
  1086.  
  1087.    Compute_HField_BBox(Object);
  1088.  
  1089.    Destroy_Image (Image);
  1090.  
  1091.    return ((OBJECT *) Object);
  1092.   }
  1093.  
  1094.  
  1095.  
  1096. /*****************************************************************************
  1097. *
  1098. * FUNCTION
  1099. *
  1100. * INPUT
  1101. *   
  1102. * OUTPUT
  1103. *   
  1104. * RETURNS
  1105. *   
  1106. * AUTHOR
  1107. *   
  1108. * DESCRIPTION
  1109. *
  1110. * CHANGES
  1111. *
  1112. ******************************************************************************/
  1113.  
  1114. static OBJECT *Parse_Triangle()
  1115. {
  1116.   TRIANGLE *Object;
  1117.  
  1118.   Parse_Begin();
  1119.  
  1120.   if ((Object = (TRIANGLE *)Parse_Object_Id()) != NULL)
  1121.   {
  1122.     return((OBJECT *) Object);
  1123.   }
  1124.  
  1125.   Object = Create_Triangle();
  1126.  
  1127.   Parse_Vector(Object->P1);    Parse_Comma();
  1128.   Parse_Vector(Object->P2);    Parse_Comma();
  1129.   Parse_Vector(Object->P3);
  1130.  
  1131.   /* Note that Compute_Triangle also computes the bounding box. */
  1132.  
  1133.   if (!Compute_Triangle(Object, FALSE))
  1134.   {
  1135.     Warn(0.0, "Degenerate triangle. Please remove.");
  1136.   }
  1137.  
  1138.   Parse_Object_Mods((OBJECT *)Object);
  1139.  
  1140.   return((OBJECT *)Object);
  1141. }
  1142.  
  1143.  
  1144.  
  1145. /*****************************************************************************
  1146. *
  1147. * FUNCTION
  1148. *
  1149. * INPUT
  1150. *   
  1151. * OUTPUT
  1152. *   
  1153. * RETURNS
  1154. *   
  1155. * AUTHOR
  1156. *   
  1157. * DESCRIPTION
  1158. *
  1159. * CHANGES
  1160. *
  1161. ******************************************************************************/
  1162.  
  1163. static
  1164. OBJECT *Parse_Smooth_Triangle ()
  1165.   {
  1166.    SMOOTH_TRIANGLE *Object;
  1167.    short degen;
  1168.    DBL vlen;
  1169.  
  1170.    degen=FALSE;
  1171.  
  1172.    Parse_Begin ();
  1173.  
  1174.    if ( (Object = (SMOOTH_TRIANGLE *)Parse_Object_Id()) != NULL)
  1175.       return ((OBJECT *) Object);
  1176.  
  1177.    Object = Create_Smooth_Triangle();
  1178.  
  1179.    Parse_Vector (Object->P1);    Parse_Comma();
  1180.    Parse_Vector (Object->N1);    Parse_Comma();
  1181.  
  1182.    VLength(vlen,Object->N1);
  1183.  
  1184.    if (vlen == 0.0)
  1185.      degen=TRUE;
  1186.    else
  1187.      VNormalize (Object->N1, Object->N1);
  1188.  
  1189.    Parse_Vector (Object->P2);    Parse_Comma();
  1190.    Parse_Vector (Object->N2);    Parse_Comma();
  1191.  
  1192.    VLength(vlen,Object->N2);
  1193.  
  1194.    if (vlen == 0.0)
  1195.      degen=TRUE;
  1196.    else
  1197.      VNormalize (Object->N2, Object->N2);
  1198.  
  1199.    Parse_Vector (Object->P3);    Parse_Comma();
  1200.    Parse_Vector (Object->N3);
  1201.  
  1202.    VLength(vlen,Object->N3);
  1203.  
  1204.    if (vlen == 0.0)
  1205.      degen=TRUE;
  1206.    else
  1207.      VNormalize (Object->N3, Object->N3);
  1208.  
  1209.    if (!degen)
  1210.    {
  1211.      degen=!Compute_Triangle ((TRIANGLE *) Object,TRUE);
  1212.    }
  1213.  
  1214.    if (degen)
  1215.    {
  1216.      Warn(0.0, "Degenerate triangle. Please remove.");
  1217.    }
  1218.  
  1219.    Compute_Triangle_BBox((TRIANGLE *)Object);
  1220.  
  1221.    Parse_Object_Mods ((OBJECT *)Object);
  1222.  
  1223.    return ((OBJECT *) Object);
  1224.  }
  1225.  
  1226.  
  1227.  
  1228. /*****************************************************************************
  1229. *
  1230. * FUNCTION
  1231. *
  1232. * INPUT
  1233. *   
  1234. * OUTPUT
  1235. *   
  1236. * RETURNS
  1237. *   
  1238. * AUTHOR
  1239. *   
  1240. * DESCRIPTION
  1241. *
  1242. * CHANGES
  1243. *
  1244. ******************************************************************************/
  1245.  
  1246. static
  1247. OBJECT *Parse_Quadric ()
  1248.   {
  1249.    VECTOR Min, Max;
  1250.    QUADRIC *Object;
  1251.  
  1252.    Parse_Begin ();
  1253.  
  1254.    if ( (Object = (QUADRIC *)Parse_Object_Id()) != NULL)
  1255.       return ((OBJECT *) Object);
  1256.  
  1257.    Object = Create_Quadric();
  1258.  
  1259.         Parse_Vector(Object->Square_Terms);     Parse_Comma();
  1260.         Parse_Vector(Object->Mixed_Terms);      Parse_Comma();
  1261.         Parse_Vector(Object->Terms);            Parse_Comma();
  1262.    Object->Constant = Parse_Float();
  1263.  
  1264.    Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1265.    Make_Vector(Max,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  1266.  
  1267.    Compute_Quadric_BBox(Object, Min, Max);  
  1268.  
  1269.    Parse_Object_Mods ((OBJECT *)Object);
  1270.  
  1271.    return ((OBJECT *) Object);
  1272.   }
  1273.  
  1274.  
  1275.  
  1276. /*****************************************************************************
  1277. *
  1278. * FUNCTION
  1279. *
  1280. * INPUT
  1281. *   
  1282. * OUTPUT
  1283. *   
  1284. * RETURNS
  1285. *   
  1286. * AUTHOR
  1287. *   
  1288. * DESCRIPTION
  1289. *
  1290. * CHANGES
  1291. *
  1292. ******************************************************************************/
  1293.  
  1294. static
  1295. OBJECT *Parse_Box ()
  1296.   {
  1297.    BOX *Object;
  1298.    DBL temp;
  1299.  
  1300.    Parse_Begin ();
  1301.  
  1302.    if ( (Object = (BOX *)Parse_Object_Id()) != NULL)
  1303.       return ((OBJECT *) Object);
  1304.  
  1305.    Object = Create_Box();
  1306.  
  1307.         Parse_Vector(Object->bounds[0]);     Parse_Comma();
  1308.         Parse_Vector(Object->bounds[1]);
  1309.  
  1310.     if (Object->bounds[0][X] > Object->bounds[1][X]) {
  1311.        temp = Object->bounds[0][X];
  1312.        Object->bounds[0][X] = Object->bounds[1][X];
  1313.        Object->bounds[1][X] = temp;
  1314.        }
  1315.     if (Object->bounds[0][Y] > Object->bounds[1][Y]) {
  1316.        temp = Object->bounds[0][Y];
  1317.        Object->bounds[0][Y] = Object->bounds[1][Y];
  1318.        Object->bounds[1][Y] = temp;
  1319.        }
  1320.     if (Object->bounds[0][Z] > Object->bounds[1][Z]) {
  1321.        temp = Object->bounds[0][Z];
  1322.        Object->bounds[0][Z] = Object->bounds[1][Z];
  1323.        Object->bounds[1][Z] = temp;
  1324.        }
  1325.  
  1326.    Compute_Box_BBox(Object);
  1327.  
  1328.    Parse_Object_Mods ((OBJECT *)Object);
  1329.  
  1330.    return ((OBJECT *) Object);
  1331.   }
  1332.  
  1333.  
  1334.  
  1335. /*****************************************************************************
  1336. *
  1337. * FUNCTION
  1338. *
  1339. * INPUT
  1340. *   
  1341. * OUTPUT
  1342. *   
  1343. * RETURNS
  1344. *   
  1345. * AUTHOR
  1346. *   
  1347. * DESCRIPTION
  1348. *
  1349. * CHANGES
  1350. *
  1351. ******************************************************************************/
  1352.  
  1353. static
  1354. OBJECT *Parse_Disc ()
  1355.   {
  1356.    DISC *Object;
  1357.    DBL tmpf;
  1358.  
  1359.    Parse_Begin ();
  1360.  
  1361.    if ( (Object = (DISC *)Parse_Object_Id()) != NULL)
  1362.       return ((OBJECT *) Object);
  1363.  
  1364.    Object = Create_Disc();
  1365.  
  1366.         Parse_Vector(Object->center); Parse_Comma ();
  1367.         Parse_Vector(Object->normal); Parse_Comma ();
  1368.    VNormalize(Object->normal, Object->normal);
  1369.  
  1370.    tmpf = Parse_Float(); Parse_Comma ();
  1371.    Object->oradius2 = tmpf * tmpf;
  1372.  
  1373.    EXPECT
  1374.      CASE_FLOAT
  1375.        tmpf = Parse_Float();
  1376.        Object->iradius2 = tmpf * tmpf;
  1377.      END_CASE
  1378.  
  1379.      OTHERWISE
  1380.        UNGET
  1381.        EXIT
  1382.      END_CASE
  1383.    END_EXPECT
  1384.  
  1385.    /* Calculate info needed for ray-disc intersections */
  1386.    VDot(tmpf, Object->center, Object->normal);
  1387.    Object->d = -tmpf;
  1388.  
  1389.    Compute_Disc(Object);  
  1390.  
  1391.    Parse_Object_Mods ((OBJECT *)Object);
  1392.  
  1393.    return ((OBJECT *) Object);
  1394.   }
  1395.  
  1396.  
  1397.  
  1398. /*****************************************************************************
  1399. *
  1400. * FUNCTION
  1401. *
  1402. * INPUT
  1403. *   
  1404. * OUTPUT
  1405. *   
  1406. * RETURNS
  1407. *   
  1408. * AUTHOR
  1409. *   
  1410. * DESCRIPTION
  1411. *
  1412. * CHANGES
  1413. *
  1414. ******************************************************************************/
  1415.  
  1416. static
  1417. OBJECT *Parse_Cylinder ()
  1418.   {
  1419.    CONE *Object;
  1420.  
  1421.    Parse_Begin ();
  1422.  
  1423.    if ( (Object = (CONE *)Parse_Object_Id()) != NULL)
  1424.       return ((OBJECT *) Object);
  1425.  
  1426.    Object = Create_Cylinder();
  1427.  
  1428.         Parse_Vector(Object->apex);  Parse_Comma ();
  1429.         Parse_Vector(Object->base);  Parse_Comma ();
  1430.    Object->apex_radius = Parse_Float();
  1431.    Object->base_radius = Object->apex_radius;
  1432.  
  1433.    EXPECT
  1434.      CASE(OPEN_TOKEN)
  1435.        Clear_Flag(Object, CLOSED_FLAG);
  1436.        EXIT
  1437.      END_CASE
  1438.  
  1439.      OTHERWISE
  1440.        UNGET
  1441.        EXIT
  1442.      END_CASE
  1443.    END_EXPECT
  1444.  
  1445.    Compute_Cylinder_Data((OBJECT *)Object);
  1446.  
  1447.    Compute_Cone_BBox(Object);
  1448.  
  1449.    Parse_Object_Mods ((OBJECT *)Object);
  1450.  
  1451.    return ((OBJECT *) Object);
  1452.   }
  1453.  
  1454.  
  1455.  
  1456. /*****************************************************************************
  1457. *
  1458. * FUNCTION
  1459. *
  1460. * INPUT
  1461. *   
  1462. * OUTPUT
  1463. *   
  1464. * RETURNS
  1465. *   
  1466. * AUTHOR
  1467. *   
  1468. * DESCRIPTION
  1469. *
  1470. * CHANGES
  1471. *
  1472. ******************************************************************************/
  1473.  
  1474. static
  1475. OBJECT *Parse_Cone ()
  1476.   {
  1477.    CONE *Object;
  1478.  
  1479.    Parse_Begin ();
  1480.  
  1481.    if ( (Object = (CONE *)Parse_Object_Id()) != NULL)
  1482.       return ((OBJECT *) Object);
  1483.  
  1484.    Object = Create_Cone();
  1485.  
  1486.         Parse_Vector(Object->apex);  Parse_Comma ();
  1487.         Object->apex_radius = Parse_Float();  Parse_Comma ();
  1488.  
  1489.         Parse_Vector(Object->base);  Parse_Comma ();
  1490.    Object->base_radius = Parse_Float();
  1491.  
  1492.    EXPECT
  1493.      CASE(OPEN_TOKEN)
  1494.        Clear_Flag(Object, CLOSED_FLAG);
  1495.        EXIT
  1496.      END_CASE
  1497.      
  1498.      OTHERWISE
  1499.        UNGET
  1500.        EXIT
  1501.      END_CASE
  1502.    END_EXPECT
  1503.  
  1504.    /* Compute run-time values for the cone */
  1505.    Compute_Cone_Data((OBJECT *)Object);
  1506.  
  1507.    Compute_Cone_BBox(Object);  
  1508.  
  1509.    Parse_Object_Mods ((OBJECT *)Object);
  1510.  
  1511.    return ((OBJECT *) Object);
  1512.   }
  1513.  
  1514.  
  1515.  
  1516. /*****************************************************************************
  1517. *
  1518. * FUNCTION
  1519. *
  1520. *   Parse_Blob_Element_Mods
  1521. *
  1522. * INPUT
  1523. *   
  1524. * OUTPUT
  1525. *   
  1526. * RETURNS
  1527. *   
  1528. * AUTHOR
  1529. *
  1530. *   Dieter Bayer
  1531. *   
  1532. * DESCRIPTION
  1533. *
  1534. *   -
  1535. *
  1536. * CHANGES
  1537. *
  1538. *   Sep 1994 : Creation.
  1539. *
  1540. ******************************************************************************/
  1541.  
  1542. static void Parse_Blob_Element_Mods(Element)
  1543. BLOB_ELEMENT *Element;
  1544. {
  1545.   VECTOR Local_Vector;
  1546.   MATRIX Local_Matrix;
  1547.   TRANSFORM Local_Trans;
  1548.   TEXTURE *Local_Texture;
  1549.  
  1550.   EXPECT
  1551.     CASE (TRANSLATE_TOKEN)
  1552.       Parse_Vector (Local_Vector);
  1553.       Translate_Blob_Element (Element, Local_Vector);
  1554.     END_CASE
  1555.  
  1556.     CASE (ROTATE_TOKEN)
  1557.       Parse_Vector (Local_Vector);
  1558.       Rotate_Blob_Element (Element, Local_Vector);
  1559.     END_CASE
  1560.  
  1561.     CASE (SCALE_TOKEN)
  1562.       Parse_Scale_Vector (Local_Vector);
  1563.       Scale_Blob_Element (Element, Local_Vector);
  1564.     END_CASE
  1565.  
  1566.     CASE (TRANSFORM_TOKEN)
  1567.       GET(TRANSFORM_ID_TOKEN)
  1568.       Transform_Blob_Element (Element, (TRANSFORM *)Token.Constant_Data);
  1569.     END_CASE
  1570.  
  1571.     CASE (MATRIX_TOKEN)
  1572.       Parse_Matrix (Local_Matrix);
  1573.       Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  1574.       Transform_Blob_Element (Element, &Local_Trans);
  1575.     END_CASE
  1576.  
  1577.     CASE (TEXTURE_TOKEN)
  1578.       Parse_Begin ();
  1579.       Local_Texture = Parse_Texture();
  1580.       Parse_End ();
  1581.       Link_Textures(&Element->Texture, Local_Texture);
  1582.     END_CASE
  1583.  
  1584.     CASE4 (PIGMENT_TOKEN, TNORMAL_TOKEN, FINISH_TOKEN, HALO_TOKEN)
  1585.       if (Element->Texture == NULL)
  1586.       {
  1587.         Element->Texture = Copy_Textures(Default_Texture);
  1588.       }
  1589.       else
  1590.       {
  1591.         if (Element->Texture->Type != PLAIN_PATTERN)
  1592.         {
  1593.           Link_Textures(&Element->Texture, Copy_Textures(Default_Texture));
  1594.         }
  1595.       }
  1596.       UNGET
  1597.       EXPECT
  1598.         CASE (PIGMENT_TOKEN)
  1599.           Parse_Begin ();
  1600.           Parse_Pigment(&Element->Texture->Pigment);
  1601.           Parse_End ();
  1602.         END_CASE
  1603.  
  1604.         CASE (TNORMAL_TOKEN)
  1605.           Parse_Begin ();
  1606.           Parse_Tnormal(&Element->Texture->Tnormal);
  1607.           Parse_End ();
  1608.         END_CASE
  1609.  
  1610.         CASE (FINISH_TOKEN)
  1611.           Parse_Finish(&Element->Texture->Finish);
  1612.         END_CASE
  1613.  
  1614.         CASE (HALO_TOKEN)
  1615.           Parse_Halo(&(Element->Texture->Halo));
  1616.         END_CASE
  1617.  
  1618.         OTHERWISE
  1619.           UNGET
  1620.           EXIT
  1621.         END_CASE
  1622.       END_EXPECT
  1623.     END_CASE
  1624.  
  1625.     OTHERWISE
  1626.       UNGET
  1627.       EXIT
  1628.     END_CASE
  1629.   END_EXPECT
  1630.  
  1631.   Parse_End();
  1632.  
  1633.   /* Postprocess to make sure that HAS_FILTER will be set correctly. */
  1634.  
  1635.   Post_Textures(Element->Texture);
  1636. }
  1637.  
  1638.  
  1639.  
  1640. /*****************************************************************************
  1641. *
  1642. * FUNCTION
  1643. *
  1644. *   Parse_Blob
  1645. *
  1646. * INPUT
  1647. *
  1648. * OUTPUT
  1649. *   
  1650. * RETURNS
  1651. *   
  1652. * AUTHOR
  1653. *
  1654. *   Dieter Bayer
  1655. *   
  1656. * DESCRIPTION
  1657. *
  1658. *   -
  1659. *
  1660. * CHANGES
  1661. *
  1662. *   Jul 1994 : Creation.
  1663. *
  1664. ******************************************************************************/
  1665.  
  1666. static OBJECT *Parse_Blob()
  1667. {
  1668.   int npoints;
  1669.   DBL threshold;
  1670.   VECTOR Axis, Base, Apex;
  1671.   BLOB *Object;
  1672.   BLOB_LIST *blob_components, *blob_component;
  1673.  
  1674.   Parse_Begin();
  1675.  
  1676.   if ((Object = (BLOB *)Parse_Object_Id()) != NULL)
  1677.   {
  1678.     return ((OBJECT *) Object);
  1679.   }
  1680.  
  1681.   Object = Create_Blob();
  1682.  
  1683.   blob_components = NULL;
  1684.  
  1685.   npoints = 0;
  1686.  
  1687.   threshold = 1.0;
  1688.  
  1689.   EXPECT
  1690.     CASE (THRESHOLD_TOKEN)
  1691.       threshold = Parse_Float();
  1692.     END_CASE
  1693.  
  1694.     /*************************************************************************
  1695.      * Read sperical component (old syntax).
  1696.      *************************************************************************/
  1697.  
  1698.     CASE (COMPONENT_TOKEN)
  1699.       blob_component = Create_Blob_List_Element();
  1700.  
  1701.       blob_component->elem.Type = BLOB_SPHERE;
  1702.  
  1703.       blob_component->elem.c[2] = Parse_Float();
  1704.  
  1705.       Parse_Comma();
  1706.  
  1707.       blob_component->elem.rad2 = Parse_Float();
  1708.  
  1709.       Parse_Comma();
  1710.  
  1711.       blob_component->elem.rad2 = Sqr(blob_component->elem.rad2);
  1712.  
  1713.       Parse_Vector(blob_component->elem.O);
  1714.  
  1715.       /* Next component. */
  1716.  
  1717.       blob_component->next = blob_components;
  1718.  
  1719.       blob_components = blob_component;
  1720.  
  1721.       npoints++;
  1722.     END_CASE
  1723.  
  1724.     /*************************************************************************
  1725.      * Read sperical component (new syntax).
  1726.      *************************************************************************/
  1727.  
  1728.     CASE (SPHERE_TOKEN)
  1729.       blob_component = Create_Blob_List_Element();
  1730.  
  1731.       blob_component->elem.Type = BLOB_SPHERE;
  1732.  
  1733.       Parse_Begin();
  1734.  
  1735.       Parse_Vector(blob_component->elem.O);
  1736.  
  1737.       Parse_Comma();
  1738.  
  1739.       blob_component->elem.rad2 = Parse_Float();
  1740.  
  1741.       blob_component->elem.rad2 = Sqr(blob_component->elem.rad2);
  1742.  
  1743.       Parse_Comma();
  1744.  
  1745.       ALLOW(STRENGTH_TOKEN)
  1746.  
  1747.       blob_component->elem.c[2] = Parse_Float();
  1748.  
  1749.       Parse_Blob_Element_Mods(&blob_component->elem);
  1750.  
  1751.       /* Next component. */
  1752.  
  1753.       blob_component->next = blob_components;
  1754.  
  1755.       blob_components = blob_component;
  1756.  
  1757.       npoints++;
  1758.     END_CASE
  1759.  
  1760.     /*************************************************************************
  1761.      * Read cylindrical component.
  1762.      *************************************************************************/
  1763.  
  1764.     CASE (CYLINDER_TOKEN)
  1765.       blob_component = Create_Blob_List_Element();
  1766.  
  1767.       blob_component->elem.Type = BLOB_CYLINDER;
  1768.  
  1769.       blob_component->elem.Trans = Create_Transform();
  1770.  
  1771.       Parse_Begin();
  1772.  
  1773.       Parse_Vector(Base);
  1774.  
  1775.       Parse_Comma();
  1776.  
  1777.       Parse_Vector(Apex);
  1778.  
  1779.       Parse_Comma();
  1780.  
  1781.       blob_component->elem.rad2 = Parse_Float();
  1782.  
  1783.       blob_component->elem.rad2 = Sqr(blob_component->elem.rad2);
  1784.  
  1785.       Parse_Comma();
  1786.  
  1787.       ALLOW(STRENGTH_TOKEN)
  1788.  
  1789.       blob_component->elem.c[2] = Parse_Float();
  1790.  
  1791.       /* Calculate cylinder's coordinate system. */
  1792.  
  1793.       VSub(Axis, Apex, Base);
  1794.  
  1795.       VLength(blob_component->elem.len, Axis);
  1796.  
  1797.       if (blob_component->elem.len < EPSILON)
  1798.       {
  1799.         Error("Degenerate cylindrical component in blob.\n");
  1800.       }
  1801.  
  1802.       VInverseScaleEq(Axis, blob_component->elem.len);
  1803.  
  1804.       Compute_Coordinate_Transform(blob_component->elem.Trans, Base, Axis, 1.0, 1.0);
  1805.  
  1806.       Parse_Blob_Element_Mods(&blob_component->elem);
  1807.  
  1808.       /* Next component. */
  1809.  
  1810.       blob_component->next = blob_components;
  1811.  
  1812.       blob_components = blob_component;
  1813.  
  1814.       npoints++;
  1815.     END_CASE
  1816.  
  1817.     OTHERWISE
  1818.       UNGET
  1819.       EXIT
  1820.     END_CASE
  1821.   END_EXPECT
  1822.  
  1823.   Create_Blob_Element_Texture_List(Object, blob_components, npoints);
  1824.  
  1825.   Parse_Object_Mods((OBJECT *)Object);
  1826.  
  1827.   /* The blob's texture has to be processed before Make_Blob() is called. */
  1828.  
  1829.   Post_Textures(Object->Texture);
  1830.   
  1831.   /* Finally, process the information */
  1832.  
  1833.   Make_Blob(Object, threshold, blob_components, npoints);
  1834.  
  1835.   return((OBJECT *)Object);
  1836. }
  1837.  
  1838.  
  1839.  
  1840. /*****************************************************************************
  1841. *
  1842. * FUNCTION
  1843. *
  1844. *   Parse_Julia_Fractal
  1845. *
  1846. * INPUT None
  1847. *   
  1848. * OUTPUT Fractal Objecstructure filledt
  1849. *   
  1850. * RETURNS 
  1851. *
  1852. *   OBJECT * -
  1853. *   
  1854. * AUTHOR
  1855. *
  1856. *   Pascal Massimino
  1857. *   
  1858. * DESCRIPTION
  1859. *
  1860. *   -
  1861. *
  1862. * CHANGES
  1863. *
  1864. *   Dec 1994 : Adopted to version 3.0. [DB]
  1865. *   Sept 1995 : Total rewrite for new syntax [TW]
  1866. *
  1867. ******************************************************************************/
  1868.  
  1869. static OBJECT *Parse_Julia_Fractal ()
  1870. {
  1871.   FRACTAL *Object;
  1872.   DBL P;
  1873.  
  1874.   Parse_Begin();
  1875.  
  1876.   if ( (Object = (FRACTAL *)Parse_Object_Id()) != NULL)
  1877.     return((OBJECT *)Object);
  1878.  
  1879.   Object = Create_Fractal();
  1880.  
  1881.   Parse_Vector4D(Object->Julia_Parm); 
  1882.  
  1883.   EXPECT
  1884.  
  1885.     CASE(MAX_ITERATION_TOKEN)
  1886.       Object->n = (int)floor(Parse_Float()); 
  1887.  
  1888.       if (Object->n <= 0)
  1889.       {
  1890.         Object->n = 1;
  1891.       }
  1892.     END_CASE
  1893.  
  1894.     CASE(SLICE_TOKEN)
  1895.       Parse_Vector4D(Object->Slice);
  1896.       Parse_Comma();
  1897.       Object->SliceDist = Parse_Float(); 
  1898.  
  1899.       /* normalize slice vector */
  1900.       V4D_Dot(P,Object->Slice, Object->Slice);
  1901.       if (fabs(P) < EPSILON)
  1902.       {
  1903.         Error("Slice vector is zero.\n");
  1904.       }
  1905.       if (fabs(Object->Slice[T]) < EPSILON)
  1906.       {
  1907.         Error("Slice t component is zero.\n");
  1908.       }
  1909.       P = sqrt(P);
  1910.       V4D_InverseScaleEq(Object->Slice, P);      
  1911.  
  1912.     END_CASE
  1913.  
  1914.     CASE(PRECISION_TOKEN)
  1915.       P = Parse_Float(); 
  1916.       if ( P < 1.0 )
  1917.       {
  1918.         P = 1.0;
  1919.       }
  1920.       Object->Precision = 1.0 / P;
  1921.     END_CASE
  1922.       
  1923.     CASE(FLOAT_FUNCT_TOKEN)
  1924.       switch(Token.Function_Id)
  1925.       {
  1926.         case EXP_TOKEN:
  1927.           Object->Sub_Type = EXP_STYPE;
  1928.           break;
  1929.         case LOG_TOKEN:
  1930.           Object->Sub_Type = LOG_STYPE;
  1931.           break;
  1932.         case SIN_TOKEN:
  1933.           Object->Sub_Type = SIN_STYPE;
  1934.           break;
  1935.         case ASIN_TOKEN:
  1936.           Object->Sub_Type = ASIN_STYPE;
  1937.           break;
  1938.         case COS_TOKEN:
  1939.           Object->Sub_Type = COS_STYPE;
  1940.           break;
  1941.         case ACOS_TOKEN:
  1942.           Object->Sub_Type = ACOS_STYPE;
  1943.           break;
  1944.         default: Parse_Error_Str ("fractal keyword");
  1945.       }    
  1946.     END_CASE
  1947.  
  1948.     /* if any of the next become supported by the expression parser,
  1949.      * then their handling would need to move above to the FUNC_TOKEN
  1950.      * case above.
  1951.      */
  1952.     CASE(ATAN_TOKEN)
  1953.       Object->Sub_Type = ATAN_STYPE;
  1954.     END_CASE
  1955.  
  1956.     CASE(COSH_TOKEN)
  1957.       Object->Sub_Type = COSH_STYPE;
  1958.     END_CASE
  1959.  
  1960.     CASE(SINH_TOKEN)
  1961.       Object->Sub_Type = SINH_STYPE;
  1962.     END_CASE
  1963.  
  1964.     CASE(TANH_TOKEN)
  1965.       Object->Sub_Type = TANH_STYPE;
  1966.     END_CASE
  1967.  
  1968.     CASE(ATANH_TOKEN)
  1969.       Object->Sub_Type = ATANH_STYPE;
  1970.     END_CASE
  1971.  
  1972.     CASE(ACOSH_TOKEN)
  1973.       Object->Sub_Type = ACOSH_STYPE;
  1974.     END_CASE
  1975.  
  1976.     CASE(ASINH_TOKEN)
  1977.       Object->Sub_Type = ASINH_STYPE;
  1978.     END_CASE
  1979.  
  1980.     CASE(SQR_TOKEN)
  1981.       Object->Sub_Type = SQR_STYPE;
  1982.     END_CASE
  1983.  
  1984.     CASE(PWR_TOKEN)
  1985.       Object->Sub_Type = PWR_STYPE;
  1986.       Parse_Float_Param2(&Object->exponent.x,&Object->exponent.y);
  1987.     END_CASE
  1988.  
  1989.     CASE(CUBE_TOKEN)
  1990.       Object->Sub_Type = CUBE_STYPE;
  1991.     END_CASE
  1992.  
  1993.     CASE(RECIPROCAL_TOKEN)
  1994.       Object->Sub_Type = RECIPROCAL_STYPE;
  1995.     END_CASE
  1996.  
  1997.     CASE(HYPERCOMPLEX_TOKEN)
  1998.       Object->Algebra = HYPERCOMPLEX_TYPE;
  1999.     END_CASE
  2000.  
  2001.     CASE(QUATERNION_TOKEN)
  2002.       Object->Algebra = QUATERNION_TYPE;
  2003.     END_CASE
  2004.  
  2005.     OTHERWISE
  2006.       UNGET
  2007.       EXIT
  2008.     END_CASE
  2009.  
  2010.   END_EXPECT
  2011.  
  2012.   Parse_Object_Mods((OBJECT *)Object);
  2013.  
  2014.   SetUp_Fractal(Object);
  2015.  
  2016.   return((OBJECT *)Object);
  2017. }
  2018.  
  2019.  
  2020.  
  2021.  
  2022. /*****************************************************************************
  2023. *
  2024. * FUNCTION
  2025. *
  2026. *   Parse_Polygon
  2027. *
  2028. * INPUT
  2029. *
  2030. * OUTPUT
  2031. *
  2032. * RETURNS
  2033. *
  2034. *   OBJECT * -
  2035. *
  2036. * AUTHOR
  2037. *
  2038. *   Dieter Bayer
  2039. *   
  2040. * DESCRIPTION
  2041. *
  2042. *   -
  2043. *
  2044. * CHANGES
  2045. *
  2046. *   May 1994 : Creation.
  2047. *
  2048. *   Oct 1994 : Modified to use new polygon data structure. [DB]
  2049. *
  2050. ******************************************************************************/
  2051.  
  2052. static OBJECT *Parse_Polygon()
  2053. {
  2054.   int i, closed = FALSE;
  2055.   int Number;
  2056.   POLYGON *Object;
  2057.   VECTOR *Points, P;
  2058.  
  2059.   Parse_Begin();
  2060.  
  2061.   if ((Object = (POLYGON *)Parse_Object_Id()) != NULL)
  2062.   {
  2063.     return((OBJECT *) Object);
  2064.   }
  2065.  
  2066.   Object = Create_Polygon();
  2067.  
  2068.   Number = (int)Parse_Float();
  2069.  
  2070.   if (Number < 3)
  2071.   {
  2072.     Error("Polygon needs at least three points.");
  2073.   }
  2074.  
  2075.   Points = (VECTOR *)POV_MALLOC((Number+1)*sizeof(VECTOR), "temporary polygon points");
  2076.  
  2077.   for (i = 0; i < Number; i++)
  2078.   {
  2079.     Parse_Comma();
  2080.  
  2081.     Parse_Vector(Points[i]);
  2082.   }
  2083.  
  2084.   /* Check for closed polygons. */
  2085.  
  2086.   Assign_Vector(P, Points[0]);
  2087.  
  2088.   for (i = 1; i < Number; i++)
  2089.   {
  2090.     closed = FALSE;
  2091.  
  2092.     if ((fabs(P[X] - Points[i][X]) < EPSILON) &&
  2093.         (fabs(P[Y] - Points[i][Y]) < EPSILON) &&
  2094.         (fabs(P[Z] - Points[i][Z]) < EPSILON))
  2095.     {
  2096.       i++;
  2097.  
  2098.       if (i < Number)
  2099.       {
  2100.         Assign_Vector(P, Points[i]);
  2101.       }
  2102.  
  2103.       closed = TRUE;
  2104.     }
  2105.   }
  2106.  
  2107.   if (!closed)
  2108.   {
  2109.     Warn(0.0, "Polygon not closed. Closing it.");
  2110.  
  2111.     Assign_Vector(Points[Number], P);
  2112.  
  2113.     Number++;
  2114.   }
  2115.  
  2116.   Compute_Polygon(Object, Number, Points);
  2117.  
  2118.   POV_FREE (Points);
  2119.  
  2120.   Parse_Object_Mods ((OBJECT *)Object);
  2121.  
  2122.   return((OBJECT *) Object);
  2123. }
  2124.  
  2125.  
  2126.  
  2127. /*****************************************************************************
  2128. *
  2129. * FUNCTION
  2130. *
  2131. *   Parse_Prism
  2132. *
  2133. * INPUT
  2134. *
  2135. * OUTPUT
  2136. *
  2137. * RETURNS
  2138. *
  2139. *   OBJECT * -
  2140. *
  2141. * AUTHOR
  2142. *
  2143. *   Dieter Bayer
  2144. *
  2145. * DESCRIPTION
  2146. *
  2147. *   -
  2148. *
  2149. * CHANGES
  2150. *
  2151. *   May 1994 : Creation.
  2152. *
  2153. ******************************************************************************/
  2154.  
  2155. static OBJECT *Parse_Prism()
  2156. {
  2157.   int i, closed = FALSE;
  2158.   DBL h;
  2159.  
  2160.   PRISM *Object;
  2161.   UV_VECT *Points, P;
  2162.  
  2163.   Parse_Begin();
  2164.  
  2165.   if ((Object = (PRISM *)Parse_Object_Id()) != NULL)
  2166.   {
  2167.     return((OBJECT *) Object);
  2168.   }
  2169.  
  2170.   Object = Create_Prism();
  2171.  
  2172.   /* 
  2173.    * Determine kind of spline used (linear, quadratic, cubic) 
  2174.    * and type of sweeping (linear, conic).
  2175.    */
  2176.  
  2177.   EXPECT
  2178.     CASE(LINEAR_SPLINE_TOKEN)
  2179.       Object->Spline_Type = LINEAR_SPLINE;
  2180.     END_CASE
  2181.  
  2182.     CASE(QUADRATIC_SPLINE_TOKEN)
  2183.       Object->Spline_Type = QUADRATIC_SPLINE;
  2184.     END_CASE
  2185.  
  2186.     CASE(CUBIC_SPLINE_TOKEN)
  2187.       Object->Spline_Type = CUBIC_SPLINE;
  2188.     END_CASE
  2189.  
  2190.     CASE(LINEAR_SWEEP_TOKEN)
  2191.       Object->Sweep_Type = LINEAR_SWEEP;
  2192.     END_CASE
  2193.  
  2194.     CASE(CONIC_SWEEP_TOKEN)
  2195.       Object->Sweep_Type = CONIC_SWEEP;
  2196.     END_CASE
  2197.  
  2198.     OTHERWISE
  2199.       UNGET
  2200.       EXIT
  2201.     END_CASE
  2202.   END_EXPECT
  2203.  
  2204.   /* Read prism heights. */
  2205.  
  2206.   Object->Height1 = Parse_Float(); Parse_Comma();
  2207.   Object->Height2 = Parse_Float(); Parse_Comma();
  2208.  
  2209.   if (Object->Height1 > Object->Height2)
  2210.   {
  2211.     h = Object->Height1;
  2212.     Object->Height1 = Object->Height2;
  2213.     Object->Height2 = h;
  2214.   }
  2215.  
  2216.   /* Get number of points = number of segments. */
  2217.  
  2218.   Object->Number = (int)Parse_Float();
  2219.  
  2220.   switch (Object->Spline_Type)
  2221.   {
  2222.     case LINEAR_SPLINE :
  2223.  
  2224.       if (Object->Number < 3)
  2225.       {
  2226.         Error("Prism with linear splines must have at least three points.");
  2227.       }
  2228.  
  2229.       break;
  2230.  
  2231.     case QUADRATIC_SPLINE :
  2232.  
  2233.       if (Object->Number < 5)
  2234.       {
  2235.         Error("Prism with quadratic splines must have at least five points.");
  2236.       }
  2237.  
  2238.       break;
  2239.  
  2240.     case CUBIC_SPLINE :
  2241.  
  2242.       if (Object->Number < 6)
  2243.       {
  2244.         Error("Prism with cubic splines must have at least six points.");
  2245.       }
  2246.   }
  2247.  
  2248.   /* Allocate Object->Number points for the prism. */
  2249.  
  2250.   Points = (UV_VECT *)POV_MALLOC((Object->Number+1) * sizeof(UV_VECT), "temporary prism points");
  2251.  
  2252.   /* Read points (x, y : coordinate of 2d point; z : not used). */
  2253.  
  2254.   for (i = 0; i < Object->Number; i++)
  2255.   {
  2256.     Parse_Comma();
  2257.  
  2258.     Parse_UV_Vect(Points[i]);
  2259.   }
  2260.  
  2261.   /* Closed or not closed that's the question. */
  2262.  
  2263.   EXPECT
  2264.     CASE(OPEN_TOKEN)
  2265.       Clear_Flag(Object, CLOSED_FLAG);
  2266.       EXIT
  2267.     END_CASE
  2268.  
  2269.     OTHERWISE
  2270.       UNGET
  2271.       EXIT
  2272.     END_CASE
  2273.   END_EXPECT
  2274.  
  2275.   /* Check for closed prism. */
  2276.  
  2277.   switch (Object->Spline_Type)
  2278.   {
  2279.     case LINEAR_SPLINE :
  2280.  
  2281.       i = 1;
  2282.  
  2283.       Assign_UV_Vect(P, Points[0]);
  2284.  
  2285.       break;
  2286.  
  2287.     case QUADRATIC_SPLINE :
  2288.     case CUBIC_SPLINE :
  2289.  
  2290.       i = 2;
  2291.  
  2292.       Assign_UV_Vect(P, Points[1]);
  2293.  
  2294.       break;
  2295.   }
  2296.  
  2297.   for ( ; i < Object->Number; i++)
  2298.   {
  2299.     closed = FALSE;
  2300.  
  2301.     if ((fabs(P[X] - Points[i][X]) < EPSILON) &&
  2302.         (fabs(P[Y] - Points[i][Y]) < EPSILON))
  2303.     {
  2304.       switch (Object->Spline_Type)
  2305.       {
  2306.         case LINEAR_SPLINE :
  2307.  
  2308.           i++;
  2309.  
  2310.           if (i < Object->Number)
  2311.           {
  2312.             Assign_UV_Vect(P, Points[i]);
  2313.           }
  2314.  
  2315.           break;
  2316.  
  2317.         case QUADRATIC_SPLINE :
  2318.  
  2319.           i += 2;
  2320.  
  2321.           if (i < Object->Number)
  2322.           {
  2323.             Assign_UV_Vect(P, Points[i]);
  2324.           }
  2325.  
  2326.           break;
  2327.  
  2328.         case CUBIC_SPLINE :
  2329.  
  2330.           i += 3;
  2331.  
  2332.           if (i < Object->Number)
  2333.           {
  2334.             Assign_UV_Vect(P, Points[i]);
  2335.           }
  2336.  
  2337.           break;
  2338.       }
  2339.  
  2340.       closed = TRUE;
  2341.     }
  2342.   }
  2343.  
  2344.   if (!closed)
  2345.   {
  2346.     if (Object->Spline_Type == LINEAR_SPLINE)
  2347.     {
  2348.       Assign_UV_Vect(Points[Object->Number], P);
  2349.  
  2350.       Object->Number++;
  2351.  
  2352.       Warn(0.0, "Linear prism not closed. Closing it.");
  2353.     }
  2354.     else
  2355.     {
  2356.       Set_Flag(Object, DEGENERATE_FLAG);
  2357.  
  2358.       Warn(0.0, "Prism not closed. Ignoring it.");
  2359.     }
  2360.   }
  2361.  
  2362.   /* Compute spline segments. */
  2363.  
  2364.   Compute_Prism(Object, Points);
  2365.  
  2366.   /* Compute bounding box. */
  2367.  
  2368.   Compute_Prism_BBox(Object);
  2369.  
  2370.   /* Parse object's modifiers. */
  2371.  
  2372.   Parse_Object_Mods((OBJECT *)Object);
  2373.  
  2374.   /* Destroy temporary points. */
  2375.  
  2376.   POV_FREE (Points);
  2377.  
  2378.   return((OBJECT *) Object);
  2379. }
  2380.  
  2381.  
  2382.  
  2383. /*****************************************************************************
  2384. *
  2385. * FUNCTION
  2386. *
  2387. *   Parse_Sor
  2388. *
  2389. * INPUT
  2390. *   
  2391. * OUTPUT
  2392. *   
  2393. * RETURNS
  2394. *
  2395. *   OBJECT * -
  2396. *
  2397. * AUTHOR
  2398. *
  2399. *   Dieter Bayer
  2400. *   
  2401. * DESCRIPTION
  2402. *
  2403. *   Read a surface of revolution primitive.
  2404. *
  2405. * CHANGES
  2406. *
  2407. *   May 1994 : Creation.
  2408. *
  2409. ******************************************************************************/
  2410.  
  2411. static OBJECT *Parse_Sor()
  2412. {
  2413.   int i;
  2414.   SOR *Object;
  2415.   UV_VECT *Points;
  2416.  
  2417.   Parse_Begin();
  2418.  
  2419.   if ((Object = (SOR *)Parse_Object_Id()) != NULL)
  2420.   {
  2421.     return((OBJECT *)Object);
  2422.   }
  2423.  
  2424.   Object = Create_Sor();
  2425.  
  2426.   /* Get number of points. */
  2427.  
  2428.   Object->Number = (int)Parse_Float();
  2429.  
  2430.   if (Object->Number <4)
  2431.   {
  2432.     Error("Surface of revolution must have at least four points.");
  2433.   }
  2434.  
  2435.   /* Get temporary points describing the rotated curve. */
  2436.  
  2437.   Points = (UV_VECT *)POV_MALLOC(Object->Number*sizeof(UV_VECT), "temporary surface of revolution points");
  2438.  
  2439.   /* Read points (x : radius; y : height; z : not used). */
  2440.  
  2441.   for (i = 0; i < Object->Number; i++)
  2442.   {
  2443.     Parse_Comma();
  2444.  
  2445.     Parse_UV_Vect(Points[i]);
  2446.  
  2447.     if ((Points[i][X] < 0.0) ||
  2448.         ((i > 1 ) && (i < Object->Number - 1) && (Points[i][Y] <= Points[i-1][Y])))
  2449.     {
  2450.       Error("Incorrect point in surface of revolution.");
  2451.     }
  2452.   }
  2453.  
  2454.   /* Closed or not closed that's the question. */
  2455.  
  2456.   EXPECT
  2457.     CASE(OPEN_TOKEN)
  2458.       Clear_Flag(Object, CLOSED_FLAG);
  2459.       EXIT
  2460.     END_CASE
  2461.  
  2462.     OTHERWISE
  2463.       UNGET
  2464.       EXIT
  2465.     END_CASE
  2466.   END_EXPECT
  2467.  
  2468.   /* There are Number-3 segments! */
  2469.  
  2470.   Object->Number -= 3;
  2471.  
  2472.   /* Compute spline segments. */
  2473.  
  2474.   Compute_Sor(Object, Points);
  2475.  
  2476.   /* Compute bounding box. */
  2477.  
  2478.   Compute_Sor_BBox(Object);
  2479.  
  2480.   /* Parse object's modifiers. */
  2481.  
  2482.   Parse_Object_Mods((OBJECT *)Object);
  2483.  
  2484.   /* Destroy temporary points. */
  2485.  
  2486.   POV_FREE (Points);
  2487.  
  2488.   return ((OBJECT *) Object);
  2489. }
  2490.  
  2491.  
  2492.  
  2493. /*****************************************************************************
  2494. *
  2495. * FUNCTION
  2496. *
  2497. *   Parse_Lathe
  2498. *
  2499. * INPUT
  2500. *   
  2501. * OUTPUT
  2502. *   
  2503. * RETURNS
  2504. *
  2505. *   OBJECT * -
  2506. *   
  2507. * AUTHOR
  2508. *
  2509. *   Dieter Bayer
  2510. *   
  2511. * DESCRIPTION
  2512. *
  2513. *   Read a lathe primitive.
  2514. *
  2515. * CHANGES
  2516. *
  2517. *   Jun 1994 : Creation.
  2518. *
  2519. ******************************************************************************/
  2520.  
  2521. static OBJECT *Parse_Lathe()
  2522. {
  2523.   int i;
  2524.   LATHE *Object;
  2525.   UV_VECT *Points;
  2526.  
  2527.   Parse_Begin();
  2528.  
  2529.   if ((Object = (LATHE *)Parse_Object_Id()) != NULL)
  2530.   {
  2531.     return((OBJECT *)Object);
  2532.   }
  2533.  
  2534.   Object = Create_Lathe();
  2535.  
  2536.   /* Determine kind of spline used and aspect ratio. */
  2537.  
  2538.   EXPECT
  2539.     CASE(LINEAR_SPLINE_TOKEN)
  2540.       Object->Spline_Type = LINEAR_SPLINE;
  2541.     END_CASE
  2542.  
  2543.     CASE(QUADRATIC_SPLINE_TOKEN)
  2544.       Object->Spline_Type = QUADRATIC_SPLINE;
  2545.     END_CASE
  2546.  
  2547.     CASE(CUBIC_SPLINE_TOKEN)
  2548.       Object->Spline_Type = CUBIC_SPLINE;
  2549.     END_CASE
  2550.  
  2551.     OTHERWISE
  2552.       UNGET
  2553.       EXIT
  2554.     END_CASE
  2555.   END_EXPECT
  2556.  
  2557.   /* Get number of points. */
  2558.  
  2559.   Object->Number = (int)Parse_Float();
  2560.  
  2561.   /* Get temporary points describing the rotated curve. */
  2562.  
  2563.   Points = (UV_VECT *)POV_MALLOC(Object->Number*sizeof(UV_VECT), "temporary lathe points");
  2564.  
  2565.   /* Read points (x : radius; y : height; z : not used). */
  2566.  
  2567.   for (i = 0; i < Object->Number; i++)
  2568.   {
  2569.     Parse_Comma();
  2570.  
  2571.     Parse_UV_Vect(Points[i]);
  2572.  
  2573.     if ((i > 0) && (i < Object->Number - 1) && (Points[i][X] < 0.0))
  2574.     {
  2575.       Error("Incorrect point in lathe.");
  2576.     }
  2577.   }
  2578.  
  2579.   switch (Object->Spline_Type)
  2580.   {
  2581.     case LINEAR_SPLINE :
  2582.  
  2583.       Object->Number--;
  2584.  
  2585.       break;
  2586.  
  2587.     case QUADRATIC_SPLINE :
  2588.  
  2589.       Object->Number -= 2;
  2590.  
  2591.       break;
  2592.  
  2593.     case CUBIC_SPLINE :
  2594.  
  2595.       Object->Number -= 3;
  2596.  
  2597.       break;
  2598.   }
  2599.  
  2600.   if (Object->Number <1)
  2601.   {
  2602.     Error("Lathe must have at least one segment.");
  2603.   }
  2604.  
  2605.   /* Compute spline segments. */
  2606.  
  2607.   Compute_Lathe(Object, Points);
  2608.  
  2609.   /* Compute bounding box. */
  2610.  
  2611.   Compute_Lathe_BBox(Object);
  2612.  
  2613.   /* Parse object's modifiers. */
  2614.  
  2615.   Parse_Object_Mods((OBJECT *)Object);
  2616.  
  2617.   /* Destroy temporary points. */
  2618.  
  2619.   POV_FREE (Points);
  2620.  
  2621.   return((OBJECT *) Object);
  2622. }
  2623.  
  2624.  
  2625.  
  2626. /*****************************************************************************
  2627. *
  2628. * FUNCTION
  2629. *
  2630. *   Parse_Superellipsoid
  2631. *
  2632. * INPUT
  2633. *   
  2634. * OUTPUT
  2635. *   
  2636. * RETURNS
  2637. *
  2638. *   OBJECT * -
  2639. *   
  2640. * AUTHOR
  2641. *
  2642. *   Dieter Bayer
  2643. *   
  2644. * DESCRIPTION
  2645. *
  2646. *   Read a superellipsoid primitive.
  2647. *
  2648. * CHANGES
  2649. *
  2650. *   Oct 1994 : Creation.
  2651. *
  2652. ******************************************************************************/
  2653.  
  2654. static OBJECT *Parse_Superellipsoid()
  2655. {
  2656.   UV_VECT V1;
  2657.   SUPERELLIPSOID *Object;
  2658.  
  2659.   Parse_Begin();
  2660.  
  2661.   if ((Object = (SUPERELLIPSOID *)Parse_Object_Id()) != NULL)
  2662.   {
  2663.     return((OBJECT *)Object);
  2664.   }
  2665.  
  2666.   Object = Create_Superellipsoid();
  2667.  
  2668.   Parse_UV_Vect(V1);
  2669.  
  2670.   /* The x component is e, the y component is n. */
  2671.  
  2672.   Object->Power[X] = 2.0  / V1[X];
  2673.   Object->Power[Y] = V1[X] / V1[Y];
  2674.   Object->Power[Z] = 2.0  / V1[Y];
  2675.  
  2676.   /* Compute bounding box. */
  2677.  
  2678.   Compute_Superellipsoid_BBox(Object);
  2679.  
  2680.   /* Parse object's modifiers. */
  2681.  
  2682.   Parse_Object_Mods((OBJECT *)Object);
  2683.  
  2684.   return((OBJECT *) Object);
  2685. }
  2686.  
  2687.  
  2688. /*****************************************************************************
  2689. *
  2690. * FUNCTION
  2691. *
  2692. *   Parse_Torus
  2693. *
  2694. * INPUT
  2695. *   
  2696. * OUTPUT
  2697. *   
  2698. * RETURNS
  2699. *
  2700. *   OBJECT
  2701. *
  2702. * AUTHOR
  2703. *
  2704. *   Dieter Bayer
  2705. *   
  2706. * DESCRIPTION
  2707. *
  2708. *   -
  2709. *
  2710. * CHANGES
  2711. *
  2712. *   Jul 1994 : Creation.
  2713. *
  2714. ******************************************************************************/
  2715.  
  2716. static OBJECT *Parse_Torus()
  2717. {
  2718.   TORUS *Object;
  2719.  
  2720.   Parse_Begin();
  2721.  
  2722.   if ((Object = (TORUS *)Parse_Object_Id()) != NULL)
  2723.   {
  2724.     return((OBJECT *)Object);
  2725.   }
  2726.  
  2727.   Object = Create_Torus();
  2728.  
  2729.   /* Read in the two radii. */
  2730.  
  2731.   Object->R = Parse_Float(); /* Big radius */
  2732.  
  2733.   Parse_Comma();
  2734.  
  2735.   Object->r = Parse_Float(); /* Little radius */
  2736.  
  2737.   Compute_Torus_BBox(Object);
  2738.  
  2739.   Parse_Object_Mods ((OBJECT *)Object);
  2740.  
  2741.   return ((OBJECT *) Object);
  2742. }
  2743.  
  2744.  
  2745.  
  2746. /*****************************************************************************
  2747. *
  2748. * FUNCTION
  2749. *
  2750. *   Parse_Mesh_Texture
  2751. *
  2752. * INPUT
  2753. *   
  2754. * OUTPUT
  2755. *   
  2756. * RETURNS
  2757. *
  2758. *   OBJECT
  2759. *   
  2760. * AUTHOR
  2761. *
  2762. *   Dieter Bayer
  2763. *   
  2764. * DESCRIPTION
  2765. *
  2766. *   Read an individual triangle mesh texture.
  2767. *
  2768. * CHANGES
  2769. *
  2770. *   Feb 1995 : Creation.
  2771. *
  2772. ******************************************************************************/
  2773.  
  2774. static TEXTURE *Parse_Mesh_Texture()
  2775. {
  2776.   TEXTURE *Texture;
  2777.  
  2778.   Texture = NULL;
  2779.  
  2780.   EXPECT
  2781.     CASE(TEXTURE_TOKEN)
  2782.       Parse_Begin();
  2783.  
  2784.       GET(TEXTURE_ID_TOKEN);
  2785.  
  2786.       Texture = (TEXTURE *)Token.Constant_Data;
  2787.  
  2788.       Parse_End();
  2789.     END_CASE
  2790.  
  2791.     OTHERWISE
  2792.       UNGET
  2793.       EXIT
  2794.     END_CASE
  2795.   END_EXPECT
  2796.  
  2797.   return(Texture);
  2798. }
  2799.  
  2800.  
  2801.  
  2802. /*****************************************************************************
  2803. *
  2804. * FUNCTION
  2805. *
  2806. *   Parse_Mesh
  2807. *
  2808. * INPUT
  2809. *   
  2810. * OUTPUT
  2811. *   
  2812. * RETURNS
  2813. *
  2814. *   OBJECT
  2815. *   
  2816. * AUTHOR
  2817. *
  2818. *   Dieter Bayer
  2819. *   
  2820. * DESCRIPTION
  2821. *
  2822. *   Read a triangle mesh.
  2823. *
  2824. * CHANGES
  2825. *
  2826. *   Feb 1995 : Creation.
  2827. *
  2828. ******************************************************************************/
  2829.  
  2830. static OBJECT *Parse_Mesh()
  2831. {
  2832.   int i;
  2833.   int number_of_normals, number_of_textures, number_of_triangles, number_of_vertices;
  2834.   int max_normals, max_textures, max_triangles, max_vertices;
  2835.   DBL l1, l2, l3;
  2836.   VECTOR D1, D2, P1, P2, P3, N1, N2, N3, N;
  2837.   SNGL_VECT *Normals, *Vertices;
  2838.   TEXTURE **Textures;
  2839.   MESH *Object;
  2840.   MESH_TRIANGLE *Triangles;
  2841.  
  2842.   Parse_Begin();
  2843.  
  2844.   if ((Object = (MESH *)Parse_Object_Id()) != NULL)
  2845.   {
  2846.     return((OBJECT *)Object);
  2847.   }
  2848.  
  2849.   /* Create object. */
  2850.  
  2851.   Object = Create_Mesh();
  2852.  
  2853.   /* Allocate temporary normals, textures, triangles and vertices. */
  2854.  
  2855.   max_normals = 256;
  2856.  
  2857.   max_vertices = 256;
  2858.  
  2859.   max_textures = 16;
  2860.  
  2861.   max_triangles = 256;
  2862.  
  2863.   Normals = (SNGL_VECT *)POV_MALLOC(max_normals*sizeof(SNGL_VECT), "temporary triangle mesh data");
  2864.  
  2865.   Textures = (TEXTURE **)POV_MALLOC(max_textures*sizeof(TEXTURE *), "temporary triangle mesh data");
  2866.  
  2867.   Triangles = (MESH_TRIANGLE *)POV_MALLOC(max_triangles*sizeof(MESH_TRIANGLE), "temporary triangle mesh data");
  2868.  
  2869.   Vertices = (SNGL_VECT *)POV_MALLOC(max_vertices*sizeof(SNGL_VECT), "temporary triangle mesh data");
  2870.  
  2871.   /* Read raw triangle file. */
  2872.  
  2873.   number_of_normals = 0;
  2874.  
  2875.   number_of_textures = 0;
  2876.  
  2877.   number_of_triangles = 0;
  2878.  
  2879.   number_of_vertices = 0;
  2880.  
  2881.   /* Create hash tables. */
  2882.  
  2883.   Create_Mesh_Hash_Tables();
  2884.  
  2885.   EXPECT
  2886.     CASE(TRIANGLE_TOKEN)
  2887.       Parse_Begin();
  2888.  
  2889.       Parse_Vector(P1);  Parse_Comma();
  2890.       Parse_Vector(P2);  Parse_Comma();
  2891.       Parse_Vector(P3);
  2892.  
  2893.       if (!Mesh_Degenerate(P1, P2, P3))
  2894.       {
  2895.         if (number_of_triangles >= max_triangles)
  2896.         {
  2897.           if (max_triangles >= INT_MAX/2)
  2898.           {
  2899.             Error("Too many triangles in triangle mesh.\n");
  2900.           }
  2901.  
  2902.           max_triangles *= 2;
  2903.  
  2904.           Triangles = (MESH_TRIANGLE *)POV_REALLOC(Triangles, max_triangles*sizeof(MESH_TRIANGLE), "triangle triangle mesh data");
  2905.         }
  2906.  
  2907.         /* Init triangle. */
  2908.  
  2909.         Init_Mesh_Triangle(&Triangles[number_of_triangles]);
  2910.  
  2911.         Triangles[number_of_triangles].P1 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P1);
  2912.         Triangles[number_of_triangles].P2 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P2);
  2913.         Triangles[number_of_triangles].P3 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P3);
  2914.  
  2915.         Compute_Mesh_Triangle(&Triangles[number_of_triangles], FALSE, P1, P2, P3, N);
  2916.  
  2917.         Triangles[number_of_triangles].Normal_Ind = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N);
  2918.  
  2919.         Triangles[number_of_triangles].Texture = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, Parse_Mesh_Texture());
  2920.  
  2921.         number_of_triangles++;
  2922.       }
  2923.  
  2924.       Parse_End();
  2925.     END_CASE
  2926.  
  2927.     CASE(SMOOTH_TRIANGLE_TOKEN)
  2928.       Parse_Begin();
  2929.  
  2930.       Parse_Vector(P1);  Parse_Comma();
  2931.       Parse_Vector(N1);  Parse_Comma();
  2932.  
  2933.       Parse_Vector(P2);  Parse_Comma();
  2934.       Parse_Vector(N2);  Parse_Comma();
  2935.  
  2936.       Parse_Vector(P3);  Parse_Comma();
  2937.       Parse_Vector(N3);
  2938.  
  2939.       VLength(l1, N1);
  2940.       VLength(l2, N2);
  2941.       VLength(l3, N3);
  2942.  
  2943.       if ((l1 != 0.0) && (l2 != 0.0) && (l3 != 0.0) && (!Mesh_Degenerate(P1, P2, P3)))
  2944.       {
  2945.         if (number_of_triangles >= max_triangles)
  2946.         {
  2947.           if (max_triangles >= INT_MAX/2)
  2948.           {
  2949.             Error("Too many triangles in triangle mesh.\n");
  2950.           }
  2951.  
  2952.           max_triangles *= 2;
  2953.  
  2954.           Triangles = (MESH_TRIANGLE *)POV_REALLOC(Triangles, max_triangles*sizeof(MESH_TRIANGLE), "triangle triangle mesh data");
  2955.         }
  2956.  
  2957.         VInverseScaleEq(N1, l1);
  2958.         VInverseScaleEq(N2, l2);
  2959.         VInverseScaleEq(N3, l3);
  2960.  
  2961.         /* Init triangle. */
  2962.  
  2963.         Init_Mesh_Triangle(&Triangles[number_of_triangles]);
  2964.  
  2965.         Triangles[number_of_triangles].P1 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P1);
  2966.         Triangles[number_of_triangles].P2 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P2);
  2967.         Triangles[number_of_triangles].P3 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P3);
  2968.  
  2969.         /* Check for equal normals. */
  2970.  
  2971.         VSub(D1, N1, N2);
  2972.         VSub(D2, N1, N3);
  2973.  
  2974.         VDot(l1, D1, D1);
  2975.         VDot(l2, D2, D2);
  2976.  
  2977.         if ((fabs(l1) > EPSILON) || (fabs(l2) > EPSILON))
  2978.         {
  2979.           /* Smooth triangle. */
  2980.  
  2981.           Triangles[number_of_triangles].N1 = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N1);
  2982.           Triangles[number_of_triangles].N2 = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N2);
  2983.           Triangles[number_of_triangles].N3 = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N3);
  2984.  
  2985.           Compute_Mesh_Triangle(&Triangles[number_of_triangles], TRUE, P1, P2, P3, N);
  2986.         }
  2987.         else
  2988.         {
  2989.           /* Flat triangle. */
  2990.  
  2991.           Compute_Mesh_Triangle(&Triangles[number_of_triangles], FALSE, P1, P2, P3, N);
  2992.         }
  2993.  
  2994.         Triangles[number_of_triangles].Normal_Ind = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N);
  2995.  
  2996.         Triangles[number_of_triangles].Texture = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, Parse_Mesh_Texture());
  2997.  
  2998.         number_of_triangles++;
  2999.       }
  3000.  
  3001.       Parse_End();
  3002.     END_CASE
  3003.  
  3004.     OTHERWISE
  3005.       UNGET
  3006.       EXIT
  3007.     END_CASE
  3008.   END_EXPECT
  3009.  
  3010.   /* Destroy hash tables. */
  3011.  
  3012.   Destroy_Mesh_Hash_Tables();
  3013.  
  3014.   /* If there are no triangles something went wrong. */
  3015.  
  3016.   if (number_of_triangles == 0)
  3017.   {
  3018.     Error("No triangles in triangle mesh.\n");
  3019.   }
  3020.  
  3021.   /* Init triangle mesh data. */
  3022.  
  3023.   Object->Data = POV_MALLOC(sizeof(MESH_DATA), "triangle mesh data");
  3024.  
  3025.   Object->Data->References = 1;
  3026.  
  3027.   Object->Data->Tree = NULL;
  3028.   
  3029.   Object->Data->Normals   = NULL;
  3030.   Object->Data->Textures  = NULL;
  3031.   Object->Data->Triangles = NULL;
  3032.   Object->Data->Vertices  = NULL;
  3033.  
  3034.   /* Allocate memory for normals, textures, triangles and vertices. */
  3035.  
  3036.   Object->Data->Number_Of_Normals = number_of_normals;
  3037.  
  3038.   Object->Data->Number_Of_Textures = number_of_textures;
  3039.  
  3040.   Object->Data->Number_Of_Triangles = number_of_triangles;
  3041.  
  3042.   Object->Data->Number_Of_Vertices = number_of_vertices;
  3043.  
  3044.   Object->Data->Normals = (SNGL_VECT *)POV_MALLOC(number_of_normals*sizeof(SNGL_VECT), "triangle mesh data");
  3045.  
  3046.   if (number_of_textures)
  3047.   {
  3048.     Set_Flag(Object, MULTITEXTURE_FLAG);
  3049.  
  3050.     Object->Data->Textures = (TEXTURE **)POV_MALLOC(number_of_textures*sizeof(TEXTURE *), "triangle mesh data");
  3051.   }
  3052.  
  3053.   Object->Data->Triangles = (MESH_TRIANGLE *)POV_MALLOC(number_of_triangles*sizeof(MESH_TRIANGLE), "triangle mesh data");
  3054.  
  3055.   Object->Data->Vertices = (SNGL_VECT *)POV_MALLOC(number_of_vertices*sizeof(SNGL_VECT), "triangle mesh data");
  3056.  
  3057.   /* Copy normals, textures, triangles and vertices into mesh. */
  3058.  
  3059.   for (i = 0; i < number_of_normals; i++)
  3060.   {
  3061.     Assign_SNGL_Vect(Object->Data->Normals[i], Normals[i]);
  3062.   }
  3063.  
  3064.   for (i = 0; i < number_of_textures; i++)
  3065.   {
  3066.     Object->Data->Textures[i] = Textures[i];
  3067.   }
  3068.  
  3069.   for (i = 0; i < number_of_triangles; i++)
  3070.   {
  3071.     Object->Data->Triangles[i] = Triangles[i];
  3072.   }
  3073.  
  3074.   for (i = 0; i < number_of_vertices; i++)
  3075.   {
  3076.     Assign_SNGL_Vect(Object->Data->Vertices[i], Vertices[i]);
  3077.   }
  3078.  
  3079.   /* Free temporary memory. */
  3080.  
  3081.   POV_FREE(Normals);
  3082.   POV_FREE(Textures);
  3083.   POV_FREE(Triangles);
  3084.   POV_FREE(Vertices);
  3085.  
  3086. /*
  3087.   Render_Info("Mesh: %ld bytes: %ld vertices, %ld normals, %ld textures, %ld triangles\n",
  3088.     Object->Data->Number_Of_Normals*sizeof(SNGL_VECT)+
  3089.     Object->Data->Number_Of_Textures*sizeof(TEXTURE *)+
  3090.     Object->Data->Number_Of_Triangles*sizeof(MESH_TRIANGLE)+
  3091.     Object->Data->Number_Of_Vertices*sizeof(SNGL_VECT),
  3092.     Object->Data->Number_Of_Vertices,
  3093.     Object->Data->Number_Of_Normals,
  3094.     Object->Data->Number_Of_Textures,
  3095.     Object->Data->Number_Of_Triangles);
  3096. */
  3097.  
  3098.   /* Create bounding box. */
  3099.  
  3100.   Compute_Mesh_BBox(Object);
  3101.  
  3102.   /* Parse object modifiers. */
  3103.  
  3104.   Parse_Object_Mods((OBJECT *)Object);
  3105.  
  3106.   /* Create bounding box tree. */
  3107.  
  3108.   Build_Mesh_BBox_Tree(Object);
  3109.  
  3110.   return((OBJECT *)Object);
  3111. }
  3112.  
  3113.  
  3114.  
  3115. /*****************************************************************************
  3116. *
  3117. * FUNCTION
  3118. *
  3119. * INPUT
  3120. *   
  3121. * OUTPUT
  3122. *   
  3123. * RETURNS
  3124. *   
  3125. * AUTHOR
  3126. *   
  3127. * DESCRIPTION
  3128. *
  3129. * CHANGES
  3130. *
  3131. ******************************************************************************/
  3132.  
  3133. static
  3134. OBJECT *Parse_Poly (order)
  3135.   int order;
  3136.   {
  3137.    POLY *Object;
  3138.  
  3139.    Parse_Begin ();
  3140.  
  3141.    if ( (Object = (POLY *)Parse_Object_Id()) != NULL)
  3142.       return ((OBJECT *) Object);
  3143.  
  3144.    if (order == 0)
  3145.      {
  3146.       order = (int)Parse_Float();      Parse_Comma();
  3147.       if (order < 2 || order > MAX_ORDER)
  3148.         Error("Order of poly is out of range.");
  3149.      }
  3150.  
  3151.    Object = Create_Poly(order);
  3152.  
  3153.    Parse_Coeffs(Object->Order, &(Object->Coeffs[0]));
  3154.  
  3155.    Compute_Poly_BBox(Object);
  3156.  
  3157.    Parse_Object_Mods ((OBJECT *)Object);
  3158.  
  3159.    return ((OBJECT *) Object);
  3160.   }
  3161.  
  3162.  
  3163.  
  3164. /*****************************************************************************
  3165. *
  3166. * FUNCTION
  3167. *
  3168. * INPUT
  3169. *   
  3170. * OUTPUT
  3171. *   
  3172. * RETURNS
  3173. *   
  3174. * AUTHOR
  3175. *   
  3176. * DESCRIPTION
  3177. *
  3178. * CHANGES
  3179. *
  3180. ******************************************************************************/
  3181.  
  3182. static
  3183. OBJECT *Parse_Bicubic_Patch ()
  3184.   {
  3185.    BICUBIC_PATCH *Object;
  3186.    int i, j;
  3187.  
  3188.    Parse_Begin ();
  3189.  
  3190.    if ( (Object = (BICUBIC_PATCH *)Parse_Object_Id()) != NULL)
  3191.       return ((OBJECT *) Object);
  3192.  
  3193.    Object = Create_Bicubic_Patch();
  3194.  
  3195.    EXPECT
  3196.      CASE_FLOAT
  3197.        Warn(1.5, "Should use keywords for bicubic parameters.");
  3198.        Object->Patch_Type = (int)Parse_Float();
  3199.        if (Object->Patch_Type == 2 ||
  3200.            Object->Patch_Type == 3)
  3201.            Object->Flatness_Value = Parse_Float();
  3202.          else
  3203.            Object->Flatness_Value = 0.1;
  3204.        Object->U_Steps = (int)Parse_Float();
  3205.        Object->V_Steps = (int)Parse_Float();
  3206.        EXIT
  3207.      END_CASE
  3208.        
  3209.      CASE (TYPE_TOKEN)
  3210.        Object->Patch_Type = (int)Parse_Float();
  3211.      END_CASE
  3212.  
  3213.      CASE (FLATNESS_TOKEN)
  3214.        Object->Flatness_Value = Parse_Float();
  3215.      END_CASE
  3216.  
  3217.      CASE (V_STEPS_TOKEN)
  3218.        Object->V_Steps = (int)Parse_Float();
  3219.      END_CASE
  3220.  
  3221.      CASE (U_STEPS_TOKEN)
  3222.        Object->U_Steps = (int)Parse_Float();
  3223.      END_CASE
  3224.  
  3225.      OTHERWISE
  3226.        UNGET
  3227.        EXIT
  3228.      END_CASE
  3229.    END_EXPECT
  3230.  
  3231.    if (Object->Patch_Type > 1)
  3232.      {
  3233.       Object->Patch_Type = 1;
  3234.       Warn(0.0, "Patch type no longer supported. Using type 1.");
  3235.      }
  3236.  
  3237.    if ((Object->Patch_Type < 0) || (Object->Patch_Type > MAX_PATCH_TYPE))
  3238.      Error("Undefined bicubic patch type.");
  3239.  
  3240.    Parse_Comma();
  3241.    for (i=0;i<4;i++)
  3242.      for (j=0;j<4;j++)
  3243.        {
  3244.                   Parse_Vector(Object->Control_Points[i][j]);
  3245.         if (!((i==3)&&(j==3)))
  3246.           Parse_Comma();
  3247.        };
  3248.    Precompute_Patch_Values(Object); /* interpolated mesh coords */
  3249.  
  3250.    Compute_Bicubic_Patch_BBox(Object);  
  3251.  
  3252.    Parse_Object_Mods ((OBJECT *)Object);
  3253.  
  3254.    return ((OBJECT *) Object);
  3255.   }
  3256.  
  3257.  
  3258.  
  3259. /*****************************************************************************
  3260. *
  3261. * FUNCTION
  3262. *
  3263. * INPUT
  3264. *   
  3265. * OUTPUT
  3266. *   
  3267. * RETURNS
  3268. *   
  3269. * AUTHOR
  3270. *   
  3271. * DESCRIPTION
  3272. *
  3273. * CHANGES
  3274. *
  3275. ******************************************************************************/
  3276.  
  3277. static
  3278. OBJECT *Parse_TrueType ()
  3279.   {
  3280.    OBJECT *Object;
  3281.    char *filename, *text_string;
  3282.    DBL depth;
  3283.    VECTOR offset;
  3284.  
  3285.    Parse_Begin ();
  3286.    
  3287.    GET(TTF_TOKEN);
  3288.  
  3289.    if ( (Object = (OBJECT *)Parse_Object_Id()) != NULL)
  3290.       return ((OBJECT *) Object);
  3291.       
  3292.    Object = (OBJECT *)Create_CSG_Union ();
  3293.    /*** Object = Create_TTF(); */
  3294.  
  3295.    /* Parse the TrueType font file name */
  3296.    filename = Parse_String();
  3297.    Parse_Comma();
  3298.  
  3299.    /* Parse the text string to be rendered */
  3300.    text_string = Parse_String();
  3301.    Parse_Comma();
  3302.  
  3303.    /* Get the extrusion depth */
  3304.    depth = Parse_Float(); Parse_Comma ();
  3305.  
  3306.    /* Get the offset vector */
  3307.    Parse_Vector(offset);
  3308.  
  3309.    /* Process all this good info */
  3310.    ProcessNewTTF((OBJECT *)Object, filename, text_string, depth, offset);
  3311.  
  3312.    /* Free up the filename and text string memory */
  3313.    POV_FREE (filename);
  3314.    POV_FREE (text_string);
  3315.  
  3316.    /**** Compute_TTF_BBox(Object); */
  3317.    Compute_CSG_BBox((OBJECT *)Object);
  3318.  
  3319.    /* Get any rotate/translate or texturing stuff */
  3320.    Parse_Object_Mods ((OBJECT *)Object);
  3321.  
  3322.    return ((OBJECT *) Object);
  3323.   }
  3324.  
  3325.  
  3326.  
  3327. /*****************************************************************************
  3328. *
  3329. * FUNCTION
  3330. *
  3331. * INPUT
  3332. *   
  3333. * OUTPUT
  3334. *   
  3335. * RETURNS
  3336. *   
  3337. * AUTHOR
  3338. *   
  3339. * DESCRIPTION
  3340. *
  3341. * CHANGES
  3342. *
  3343. ******************************************************************************/
  3344.  
  3345. static
  3346. OBJECT *Parse_CSG (CSG_Type)
  3347.   int CSG_Type;
  3348.   {
  3349.    CSG *Object;
  3350.    OBJECT *Local;
  3351.    int Object_Count = 0;
  3352.  
  3353.    Parse_Begin ();
  3354.  
  3355.    if ( (Object = (CSG *)Parse_Object_Id()) != NULL)
  3356.       return ((OBJECT *) Object);
  3357.  
  3358.    if (CSG_Type & CSG_UNION_TYPE)
  3359.      Object = Create_CSG_Union ();
  3360.    else
  3361.      if (CSG_Type & CSG_MERGE_TYPE)
  3362.        Object = Create_CSG_Merge ();
  3363.      else
  3364.        Object = Create_CSG_Intersection ();
  3365.  
  3366.    Object->Children = NULL;
  3367.  
  3368.    while ((Local = Parse_Object ()) != NULL)
  3369.      {
  3370.       if ((CSG_Type & CSG_INTERSECTION_TYPE) && (Local->Type & PATCH_OBJECT))
  3371.         Warn(0.0, "Patch objects not allowed in intersection.");
  3372.       Object_Count++;
  3373.       if ((CSG_Type & CSG_DIFFERENCE_TYPE) && (Object_Count > 1))
  3374.         Invert_Object (Local);
  3375.       Object->Type |=  (Local->Type & CHILDREN_FLAGS);
  3376.       Local->Type |= IS_CHILD_OBJECT;
  3377.       Link(Local, &Local->Sibling, &Object->Children);
  3378.      };
  3379.  
  3380.    if ((Object_Count < 2) && (opts.Language_Version >= 1.5))
  3381.      Warn(1.5, "Should have at least 2 objects in csg.");
  3382.  
  3383.    Compute_CSG_BBox((OBJECT *)Object);
  3384.  
  3385.    Parse_Object_Mods ((OBJECT *)Object);
  3386.  
  3387.    return ((OBJECT *) Object);
  3388.   }
  3389.  
  3390.  
  3391.  
  3392. /*****************************************************************************
  3393. *
  3394. * FUNCTION
  3395. *
  3396. * INPUT
  3397. *
  3398. * OUTPUT
  3399. *
  3400. * RETURNS
  3401. *
  3402. * AUTHOR
  3403. *
  3404. * DESCRIPTION
  3405. *
  3406. * CHANGES
  3407. *
  3408. ******************************************************************************/
  3409.  
  3410. static
  3411. OBJECT *Parse_Light_Source ()
  3412.   {
  3413.    DBL Len;
  3414.    VECTOR Local_Vector;
  3415.    MATRIX Local_Matrix;
  3416.    TRANSFORM Local_Trans;
  3417.    LIGHT_SOURCE *Object;
  3418.  
  3419.    Parse_Begin ();
  3420.  
  3421.    if ( (Object = (LIGHT_SOURCE *)Parse_Object_Id()) != NULL)
  3422.       return ((OBJECT *) Object);
  3423.       
  3424.    Object = Create_Light_Source ();
  3425.  
  3426.    Parse_Vector(Object->Center);
  3427.  
  3428.    Parse_Comma();
  3429.  
  3430.    Parse_Colour (Object->Colour);
  3431.  
  3432.    EXPECT
  3433.      CASE (LOOKS_LIKE_TOKEN)
  3434.        if (Object->Children != NULL)
  3435.          Error("Only one looks_like allowed per light_source.");
  3436.        Parse_Begin ();
  3437.        Object->Type &= ~(int)PATCH_OBJECT;
  3438.        if ((Object->Children = Parse_Object ()) == NULL)
  3439.          Parse_Error_Str ("object");
  3440.        Compute_Translation_Transform(&Local_Trans, Object->Center);
  3441.        Translate_Object (Object->Children, Object->Center, &Local_Trans);
  3442.        Parse_Object_Mods (Object->Children);
  3443.        Set_Flag(Object->Children, NO_SHADOW_FLAG);
  3444.        Set_Flag(Object, NO_SHADOW_FLAG);
  3445.        Object->Type |= (Object->Children->Type & CHILDREN_FLAGS);
  3446.      END_CASE
  3447.  
  3448.      CASE (FILL_LIGHT_TOKEN)
  3449.        Object->Light_Type = FILL_LIGHT_SOURCE;
  3450.      END_CASE
  3451.  
  3452.      CASE (SPOTLIGHT_TOKEN)
  3453.        Object->Light_Type = SPOT_SOURCE;
  3454.      END_CASE
  3455.  
  3456.      CASE (CYLINDER_TOKEN)
  3457.        Object->Light_Type = CYLINDER_SOURCE;
  3458.      END_CASE
  3459.  
  3460.      CASE (POINT_AT_TOKEN)
  3461.        if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
  3462.          Parse_Vector(Object->Points_At);
  3463.        else
  3464.          Not_With ("point_at","standard light source");
  3465.      END_CASE
  3466.  
  3467.      CASE (TIGHTNESS_TOKEN)
  3468.        if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
  3469.          Object->Coeff = Parse_Float();
  3470.        else
  3471.          Not_With ("tightness","standard light source");
  3472.      END_CASE
  3473.  
  3474.      CASE (RADIUS_TOKEN)
  3475.        if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
  3476.          Object->Radius = Parse_Float();
  3477.        else
  3478.          Not_With ("radius","standard light source");
  3479.      END_CASE
  3480.  
  3481.      CASE (FALLOFF_TOKEN)
  3482.        if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
  3483.          Object->Falloff = Parse_Float();
  3484.        else
  3485.          Not_With ("falloff","standard light source");
  3486.      END_CASE
  3487.  
  3488.      CASE (FADE_DISTANCE_TOKEN)
  3489.        Object->Fade_Distance = Parse_Float();
  3490.      END_CASE
  3491.  
  3492.      CASE (FADE_POWER_TOKEN)
  3493.        Object->Fade_Power = Parse_Float();
  3494.      END_CASE
  3495.  
  3496.      CASE (AREA_LIGHT_TOKEN)
  3497.        Object->Area_Light = TRUE;
  3498.        Parse_Vector (Object->Axis1); Parse_Comma ();
  3499.        Parse_Vector (Object->Axis2); Parse_Comma ();
  3500.        Object->Area_Size1 = (int)Parse_Float(); Parse_Comma ();
  3501.        Object->Area_Size2 = (int)Parse_Float();
  3502.        Object->Light_Grid = Create_Light_Grid (Object->Area_Size1, Object->Area_Size2);
  3503.      END_CASE
  3504.  
  3505.      CASE (JITTER_TOKEN)
  3506.        Object->Jitter = TRUE;
  3507.      END_CASE
  3508.  
  3509.      CASE (TRACK_TOKEN)
  3510.        Object->Track = TRUE;
  3511.      END_CASE
  3512.  
  3513.      CASE (ADAPTIVE_TOKEN)
  3514.        Object->Adaptive_Level = (int)Parse_Float();
  3515.      END_CASE
  3516.  
  3517.      CASE (ATMOSPHERIC_ATTENUATION_TOKEN)
  3518.        Experimental_Flag |= EF_ATMOS;
  3519.        Object->Atmospheric_Attenuation = Allow_Float(1.0) > 0.0;
  3520.      END_CASE
  3521.  
  3522.      CASE (ATMOSPHERE_TOKEN)
  3523.        Experimental_Flag |= EF_ATMOS;
  3524.        Object->Atmosphere_Interaction = Allow_Float(1.0) > 0.0;
  3525.      END_CASE
  3526.  
  3527.      CASE (TRANSLATE_TOKEN)
  3528.        Parse_Vector (Local_Vector);
  3529.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  3530.        Translate_Object ((OBJECT *)Object, Local_Vector, &Local_Trans);
  3531.      END_CASE
  3532.  
  3533.      CASE (ROTATE_TOKEN)
  3534.        Parse_Vector (Local_Vector);
  3535.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  3536.        Rotate_Object ((OBJECT *)Object, Local_Vector, &Local_Trans);
  3537.      END_CASE
  3538.  
  3539.      CASE (SCALE_TOKEN)
  3540.        Parse_Scale_Vector (Local_Vector);
  3541.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  3542.        Scale_Object ((OBJECT *)Object, Local_Vector, &Local_Trans);
  3543.      END_CASE
  3544.  
  3545.      CASE (TRANSFORM_TOKEN)
  3546.        GET(TRANSFORM_ID_TOKEN)
  3547.        Transform_Object ((OBJECT *)Object, (TRANSFORM *)Token.Constant_Data);
  3548.      END_CASE
  3549.  
  3550.      CASE (MATRIX_TOKEN)
  3551.        Parse_Matrix (Local_Matrix);
  3552.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  3553.        Transform_Object ((OBJECT *)Object, &Local_Trans);
  3554.      END_CASE
  3555.  
  3556.      OTHERWISE
  3557.        UNGET
  3558.        EXIT
  3559.      END_CASE
  3560.    END_EXPECT
  3561.  
  3562.    Parse_End ();
  3563.  
  3564.    if (Object->Light_Type == SPOT_SOURCE)
  3565.    {
  3566.      Object->Radius  = cos(Object->Radius * M_PI_180);
  3567.      Object->Falloff = cos(Object->Falloff * M_PI_180);
  3568.    }
  3569.  
  3570.    VSub(Object->Direction, Object->Points_At, Object->Center);
  3571.  
  3572.    VLength(Len, Object->Direction);
  3573.  
  3574.    if (Len > EPSILON)
  3575.    {
  3576.      VInverseScaleEq(Object->Direction, Len);
  3577.    }
  3578.  
  3579.    return ((OBJECT *)Object);
  3580.   }
  3581.  
  3582.  
  3583.  
  3584. /*****************************************************************************
  3585. *
  3586. * FUNCTION
  3587. *
  3588. * INPUT
  3589. *   
  3590. * OUTPUT
  3591. *   
  3592. * RETURNS
  3593. *   
  3594. * AUTHOR
  3595. *   
  3596. * DESCRIPTION
  3597. *
  3598. * CHANGES
  3599. *
  3600. ******************************************************************************/
  3601.  
  3602. OBJECT *Parse_Object ()
  3603.   {
  3604.    OBJECT *Object = NULL;
  3605.  
  3606.    EXPECT
  3607.  
  3608.      CASE (JULIA_FRACTAL_TOKEN)
  3609.        Object = Parse_Julia_Fractal ();
  3610.        EXIT
  3611.      END_CASE
  3612.  
  3613.      CASE (SPHERE_TOKEN)
  3614.        Object = Parse_Sphere ();
  3615.        EXIT
  3616.      END_CASE
  3617.  
  3618.      CASE (PLANE_TOKEN)
  3619.        Object = Parse_Plane ();
  3620.        EXIT
  3621.      END_CASE
  3622.  
  3623.      CASE (CONE_TOKEN)
  3624.        Object = Parse_Cone ();
  3625.        EXIT
  3626.      END_CASE
  3627.  
  3628.      CASE (CYLINDER_TOKEN)
  3629.        Object = Parse_Cylinder ();
  3630.        EXIT
  3631.      END_CASE
  3632.  
  3633.      CASE (DISC_TOKEN)
  3634.        Object = Parse_Disc ();
  3635.        EXIT
  3636.      END_CASE
  3637.  
  3638.      CASE (QUADRIC_TOKEN)
  3639.        Object = Parse_Quadric ();
  3640.        EXIT
  3641.      END_CASE
  3642.  
  3643.      CASE (CUBIC_TOKEN)
  3644.        Object = Parse_Poly (3);
  3645.        EXIT
  3646.      END_CASE
  3647.  
  3648.      CASE (QUARTIC_TOKEN)
  3649.        Object = Parse_Poly (4);
  3650.        EXIT
  3651.      END_CASE
  3652.  
  3653.      CASE (POLY_TOKEN)
  3654.        Object = Parse_Poly (0);
  3655.        EXIT
  3656.      END_CASE
  3657.  
  3658.      CASE (TORUS_TOKEN)
  3659.        Object = Parse_Torus ();
  3660.        EXIT
  3661.      END_CASE
  3662.  
  3663.      /* Parse lathe primitive. [DB 8/94] */
  3664.  
  3665.      CASE (LATHE_TOKEN)
  3666.        Object = Parse_Lathe();
  3667.        EXIT
  3668.      END_CASE
  3669.  
  3670.      /* Parse polygon primitive. [DB 8/94] */
  3671.  
  3672.      CASE (POLYGON_TOKEN)
  3673.        Object = Parse_Polygon();
  3674.        EXIT
  3675.      END_CASE
  3676.  
  3677.      /* Parse prism primitive. [DB 8/94] */
  3678.  
  3679.      CASE (PRISM_TOKEN)
  3680.        Object = Parse_Prism();
  3681.        EXIT
  3682.      END_CASE
  3683.  
  3684.      /* Parse surface of revolution primitive. [DB 8/94] */
  3685.  
  3686.      CASE (SOR_TOKEN)
  3687.        Object = Parse_Sor();
  3688.        EXIT
  3689.      END_CASE
  3690.  
  3691.      /* Parse superellipsoid primitive. [DB 11/94] */
  3692.  
  3693.      CASE (SUPERELLIPSOID_TOKEN)
  3694.        Object = Parse_Superellipsoid();
  3695.        EXIT
  3696.      END_CASE
  3697.  
  3698.      /* Parse triangle mesh primitive. [DB 2/95] */
  3699.  
  3700.      CASE (MESH_TOKEN)
  3701.        Object = Parse_Mesh();
  3702.        EXIT
  3703.      END_CASE
  3704.  
  3705.      CASE (TEXT_TOKEN)
  3706.        Object = Parse_TrueType ();
  3707.        EXIT
  3708.      END_CASE
  3709.  
  3710.      CASE (OBJECT_ID_TOKEN)
  3711.        Object = Copy_Object((OBJECT *) Token.Constant_Data);
  3712.        EXIT
  3713.      END_CASE
  3714.  
  3715.      CASE (UNION_TOKEN)
  3716.        Object = Parse_CSG (CSG_UNION_TYPE);
  3717.        EXIT
  3718.      END_CASE
  3719.  
  3720.      CASE (COMPOSITE_TOKEN)
  3721.        Warn(1.5, "Use union instead of composite.");
  3722.        Object = Parse_CSG (CSG_UNION_TYPE);
  3723.        EXIT
  3724.      END_CASE
  3725.  
  3726.      CASE (MERGE_TOKEN)
  3727.        Object = Parse_CSG (CSG_MERGE_TYPE);
  3728.        EXIT
  3729.      END_CASE
  3730.  
  3731.      CASE (INTERSECTION_TOKEN)
  3732.        Object = Parse_CSG (CSG_INTERSECTION_TYPE);
  3733.        EXIT
  3734.      END_CASE
  3735.  
  3736.      CASE (DIFFERENCE_TOKEN)
  3737.        Object = Parse_CSG (CSG_DIFFERENCE_TYPE+CSG_INTERSECTION_TYPE);
  3738.        EXIT
  3739.      END_CASE
  3740.  
  3741.      CASE (BICUBIC_PATCH_TOKEN)
  3742.        Object = Parse_Bicubic_Patch ();
  3743.        EXIT
  3744.      END_CASE
  3745.  
  3746.      CASE (TRIANGLE_TOKEN)
  3747.        Object = Parse_Triangle ();
  3748.        EXIT
  3749.      END_CASE
  3750.  
  3751.      CASE (SMOOTH_TRIANGLE_TOKEN)
  3752.        Object = Parse_Smooth_Triangle ();
  3753.        EXIT
  3754.      END_CASE
  3755.  
  3756.      CASE (HEIGHT_FIELD_TOKEN)
  3757.        Object = Parse_HField ();
  3758.        EXIT
  3759.      END_CASE
  3760.  
  3761.      CASE (BOX_TOKEN)
  3762.        Object = Parse_Box ();
  3763.        EXIT
  3764.      END_CASE
  3765.  
  3766.      CASE (BLOB_TOKEN)
  3767.        Object = Parse_Blob ();
  3768.        EXIT
  3769.      END_CASE
  3770.  
  3771.      CASE (LIGHT_SOURCE_TOKEN)
  3772.        Object = Parse_Light_Source ();
  3773.        EXIT
  3774.      END_CASE
  3775.  
  3776.      CASE (OBJECT_TOKEN)
  3777.        Parse_Begin ();
  3778.        Object = Parse_Object ();
  3779.        if (!Object)
  3780.          Parse_Error_Str ("object");
  3781.        Parse_Object_Mods ((OBJECT *)Object);
  3782.        EXIT
  3783.      END_CASE
  3784.  
  3785.      OTHERWISE
  3786.        UNGET
  3787.        EXIT
  3788.      END_CASE
  3789.    END_EXPECT
  3790.  
  3791.    return ((OBJECT *) Object);
  3792.   }
  3793.   
  3794.  
  3795.  
  3796. /*****************************************************************************
  3797. *
  3798. * FUNCTION
  3799. *
  3800. * INPUT
  3801. *   
  3802. * OUTPUT
  3803. *   
  3804. * RETURNS
  3805. *   
  3806. * AUTHOR
  3807. *   
  3808. * DESCRIPTION
  3809. *
  3810. * CHANGES
  3811. *
  3812. ******************************************************************************/
  3813.  
  3814. void Parse_Default ()
  3815.   {
  3816.    TEXTURE *Local_Texture;
  3817.    PIGMENT *Local_Pigment;
  3818.    TNORMAL *Local_Tnormal;
  3819.    FINISH  *Local_Finish;
  3820.    HALO    *Local_Halo;
  3821.  
  3822.    Not_In_Default = FALSE;
  3823.    Parse_Begin();
  3824.    
  3825.    EXPECT
  3826.      CASE (TEXTURE_TOKEN)
  3827.        Local_Texture = Default_Texture;
  3828.        Parse_Begin ();
  3829.        Default_Texture = Parse_Texture();
  3830.        Parse_End ();
  3831.        if (Default_Texture->Type != PLAIN_PATTERN)
  3832.          Error("Default texture cannot be material map or tiles.");
  3833.        if (Default_Texture->Next != NULL)
  3834.          Error("Default texture cannot be layered.");
  3835.        Destroy_Textures(Local_Texture);
  3836.      END_CASE
  3837.  
  3838.      CASE (PIGMENT_TOKEN)
  3839.        Local_Pigment = Copy_Pigment((Default_Texture->Pigment));
  3840.        Parse_Begin ();
  3841.        Parse_Pigment (&Local_Pigment);
  3842.        Parse_End ();
  3843.        Destroy_Pigment(Default_Texture->Pigment);
  3844.        Default_Texture->Pigment = Local_Pigment;
  3845.      END_CASE
  3846.  
  3847.      CASE (TNORMAL_TOKEN)
  3848.        Local_Tnormal = Copy_Tnormal((Default_Texture->Tnormal));
  3849.        Parse_Begin ();
  3850.        Parse_Tnormal (&Local_Tnormal);
  3851.        Parse_End ();
  3852.        Destroy_Tnormal(Default_Texture->Tnormal);
  3853.        Default_Texture->Tnormal = Local_Tnormal;
  3854.      END_CASE
  3855.  
  3856.      CASE (FINISH_TOKEN)
  3857.        Local_Finish = Copy_Finish((Default_Texture->Finish));
  3858.        Parse_Finish (&Local_Finish);
  3859.        Destroy_Finish(Default_Texture->Finish);
  3860.        Default_Texture->Finish = Local_Finish;
  3861.      END_CASE
  3862.  
  3863.      CASE (HALO_TOKEN)
  3864.        Local_Halo = Copy_Halo((Default_Texture->Halo));
  3865.        Parse_Halo (&Local_Halo);
  3866.        Destroy_Halo(Default_Texture->Halo);
  3867.        Default_Texture->Halo = Local_Halo;
  3868.      END_CASE
  3869.  
  3870.      CASE (CAMERA_TOKEN)
  3871.        Parse_Camera (&Default_Camera);
  3872.      END_CASE
  3873.  
  3874.      OTHERWISE
  3875.        UNGET
  3876.        EXIT
  3877.      END_CASE
  3878.    END_EXPECT
  3879.  
  3880.    Parse_End();
  3881.  
  3882.    Not_In_Default = TRUE;
  3883. }
  3884.  
  3885.  
  3886.  
  3887. /*****************************************************************************
  3888. *
  3889. * FUNCTION
  3890. *
  3891. * INPUT
  3892. *   
  3893. * OUTPUT
  3894. *   
  3895. * RETURNS
  3896. *   
  3897. * AUTHOR
  3898. *   
  3899. * DESCRIPTION
  3900. *
  3901. * CHANGES
  3902. *
  3903. ******************************************************************************/
  3904.  
  3905. static void Parse_Frame ()
  3906.   {
  3907.    OBJECT *Object;
  3908.    RAINBOW  *Local_Rainbow;
  3909.    FOG  *Local_Fog;
  3910.    SKYSPHERE  *Local_Skysphere;
  3911.    ATMOSPHERE *Local_Atmosphere;
  3912.  
  3913.    EXPECT
  3914.      CASE (RAINBOW_TOKEN)
  3915.        Local_Rainbow = Parse_Rainbow();
  3916.        Local_Rainbow->Next = Frame.Rainbow;
  3917.        Frame.Rainbow = Local_Rainbow;
  3918.      END_CASE
  3919.  
  3920.      CASE (SKYSPHERE_TOKEN)
  3921.        Local_Skysphere = Parse_Skysphere();
  3922.        if (Frame.Skysphere != NULL)
  3923.        {
  3924.          Warn(0.0, "Only one sky-sphere allowed (last one will be used).");
  3925.          Destroy_Skysphere(Frame.Skysphere);
  3926.        }
  3927.        Frame.Skysphere = Local_Skysphere;
  3928.      END_CASE
  3929.  
  3930.      CASE (FOG_TOKEN)
  3931.        Local_Fog = Parse_Fog();
  3932.        Local_Fog->Next = Frame.Fog;
  3933.        Frame.Fog = Local_Fog;
  3934.      END_CASE
  3935.  
  3936.      CASE (ATMOSPHERE_TOKEN)
  3937.        Local_Atmosphere = Parse_Atmosphere();
  3938.        if (Frame.Atmosphere != NULL)
  3939.        {
  3940.          Warn(0.0, "Only one atmosphere allowed (last one will be used).");
  3941.          Destroy_Atmosphere(Frame.Atmosphere);
  3942.        }
  3943.        Frame.Atmosphere = Local_Atmosphere;
  3944.      END_CASE
  3945.  
  3946.      CASE (BACKGROUND_TOKEN)
  3947.        Parse_Begin();
  3948.        Parse_Colour (Frame.Background_Colour);
  3949.        Parse_End();
  3950.      END_CASE
  3951.  
  3952.      CASE (CAMERA_TOKEN)
  3953.        Parse_Camera (&Frame.Camera);
  3954.      END_CASE
  3955.  
  3956.      CASE (DECLARE_TOKEN)
  3957.        UNGET
  3958.        Warn(2.99,"Should have '#' before 'declare'.");
  3959.        Parse_Directive (FALSE);
  3960.      END_CASE
  3961.  
  3962.      CASE (INCLUDE_TOKEN)
  3963.        UNGET
  3964.        Warn(2.99,"Should have '#' before 'include'.");
  3965.        Parse_Directive (FALSE);
  3966.      END_CASE
  3967.  
  3968.      CASE (FLOAT_FUNCT_TOKEN)
  3969.        switch(Token.Function_Id)
  3970.          {
  3971.           case VERSION_TOKEN:
  3972.             UNGET
  3973.             Parse_Directive (FALSE);
  3974.             UNGET
  3975.             break;
  3976.             
  3977.           default:
  3978.             UNGET
  3979.             Parse_Error_Str ("object or directive");
  3980.             break;
  3981.          }
  3982.      END_CASE
  3983.  
  3984.      CASE (MAX_TRACE_LEVEL_TOKEN)
  3985.        Global_Setting_Warn();
  3986.        Max_Trace_Level = (int) Parse_Float ();
  3987.      END_CASE
  3988.  
  3989.      CASE (MAX_INTERSECTIONS)
  3990.        Global_Setting_Warn();
  3991.        Max_Intersections = (int)Parse_Float ();
  3992.      END_CASE
  3993.  
  3994.      CASE (DEFAULT_TOKEN)
  3995.        Parse_Default();
  3996.      END_CASE
  3997.  
  3998.      CASE (END_OF_FILE_TOKEN)
  3999.        EXIT
  4000.      END_CASE
  4001.  
  4002.      CASE (GLOBAL_SETTINGS_TOKEN)
  4003.        Parse_Global_Settings();
  4004.      END_CASE
  4005.  
  4006.      OTHERWISE
  4007.        UNGET
  4008.        Object = Parse_Object();
  4009.        if (Object == NULL)
  4010.          Parse_Error_Str ("object or directive");
  4011.        Post_Process (Object, NULL);
  4012.        Link_To_Frame (Object);
  4013.      END_CASE
  4014.    END_EXPECT
  4015.   }
  4016.  
  4017.  
  4018.  
  4019. /*****************************************************************************
  4020. *
  4021. * FUNCTION
  4022. *
  4023. * INPUT
  4024. *   
  4025. * OUTPUT
  4026. *   
  4027. * RETURNS
  4028. *   
  4029. * AUTHOR
  4030. *   
  4031. * DESCRIPTION
  4032. *
  4033. * CHANGES
  4034. *
  4035. *   Mar 1996 : Add line number info to warning message  [AED]
  4036. *
  4037. ******************************************************************************/
  4038.  
  4039. static void Global_Setting_Warn()
  4040. {
  4041.   if (opts.Language_Version >= 3.0)
  4042.   {
  4043.     Warning(0.0, "%s:%d: warning: '%s' should be in 'global_settings{...}' statement.\n",
  4044.             Token.Filename, Token.Token_Line_No+1, Token.Token_String);
  4045.   }
  4046. }
  4047.  
  4048.  
  4049.  
  4050. /*****************************************************************************
  4051. *
  4052. * FUNCTION
  4053. *
  4054. * INPUT
  4055. *   
  4056. * OUTPUT
  4057. *   
  4058. * RETURNS
  4059. *   
  4060. * AUTHOR
  4061. *   
  4062. * DESCRIPTION
  4063. *
  4064. * CHANGES
  4065. *
  4066. ******************************************************************************/
  4067.  
  4068. static void Parse_Global_Settings()
  4069. {
  4070.    Parse_Begin();
  4071.    EXPECT
  4072.      CASE (IRID_WAVELENGTH_TOKEN)
  4073.        Parse_Colour (Frame.Irid_Wavelengths);
  4074.      END_CASE
  4075.  
  4076.      CASE (ASSUMED_GAMMA_TOKEN)
  4077.      {
  4078.        DBL AssumedGamma;
  4079.        AssumedGamma = Parse_Float ();
  4080.  
  4081.        if (fabs(AssumedGamma - opts.DisplayGamma) < 0.1)
  4082.        {
  4083.          opts.GammaFactor = 1.0;
  4084.          opts.Options &= ~GAMMA_CORRECT; /* turn off gamma correction */
  4085.        }
  4086.        else
  4087.        {
  4088.          opts.GammaFactor = AssumedGamma/opts.DisplayGamma;
  4089.          opts.Options |= GAMMA_CORRECT; /* turn on gamma correction */
  4090.        }
  4091.      }
  4092.      END_CASE
  4093.  
  4094.      CASE (MAX_TRACE_LEVEL_TOKEN)
  4095.        Max_Trace_Level = (int) Parse_Float ();
  4096.      END_CASE
  4097.  
  4098.      CASE (ADC_BAILOUT_TOKEN)
  4099.        ADC_Bailout = Parse_Float ();
  4100.      END_CASE
  4101.  
  4102.      CASE (NUMBER_OF_WAVES_TOKEN)
  4103.        Number_Of_Waves = (int) Parse_Float ();
  4104.        if(Number_Of_Waves <=0)
  4105.        {
  4106.          Warn(0.0, "Illegal Value: Number_Of_Waves = 0. Changed to 1.");
  4107.          Number_Of_Waves = 1;
  4108.        }
  4109.      END_CASE
  4110.  
  4111.      CASE (MAX_INTERSECTIONS)
  4112.        Max_Intersections = (int)Parse_Float ();
  4113.      END_CASE
  4114.  
  4115.      CASE (AMBIENT_LIGHT_TOKEN)
  4116.        Parse_Colour (Frame.Ambient_Light);
  4117.      END_CASE
  4118.  
  4119.      CASE (RADIOSITY_TOKEN)
  4120.        Experimental_Flag |= EF_RADIOS;
  4121.        Parse_Begin();
  4122.        EXPECT
  4123.          CASE (BRIGHTNESS_TOKEN)
  4124.            if ((opts.Radiosity_Brightness = Parse_Float()) <= 0.0)
  4125.            {
  4126.               Error("Radiosity brightness must be a positive number.");
  4127.            }
  4128.          END_CASE
  4129.  
  4130.          CASE (COUNT_TOKEN)
  4131.            if (( opts.Radiosity_Count = (int)Parse_Float()) <= 0)
  4132.            {
  4133.              Error("Radiosity count must be a positive number.");
  4134.            }
  4135.            if ( opts.Radiosity_Count > 1600)
  4136.            {
  4137.              Error("Radiosity count can not be more than 1600.");
  4138.              opts.Radiosity_Count = 1600;
  4139.            }
  4140.          END_CASE
  4141.  
  4142.          CASE (DISTANCE_MAXIMUM_TOKEN)
  4143.            if (( opts.Radiosity_Dist_Max = Parse_Float()) < 0.0)
  4144.            {
  4145.              Error("Radiosity distance maximum must be a positive number.");
  4146.            }
  4147.          END_CASE
  4148.  
  4149.          CASE (ERROR_BOUND_TOKEN)
  4150.            if (( opts.Radiosity_Error_Bound = Parse_Float()) <= 0.0)
  4151.            {
  4152.              Error("Radiosity error bound must be a positive number.");
  4153.            }
  4154.          END_CASE
  4155.  
  4156.          CASE (GRAY_THRESHOLD_TOKEN)
  4157.            opts.Radiosity_Gray = Parse_Float();
  4158.            if (( opts.Radiosity_Gray < 0.0) || ( opts.Radiosity_Gray > 1.0))
  4159.            {
  4160.               Error("Radiosity gray threshold must be from 0.0 to 1.0.");
  4161.            }
  4162.          END_CASE
  4163.  
  4164.          CASE (LOW_ERROR_FACTOR_TOKEN)
  4165.            if (( opts.Radiosity_Low_Error_Factor = Parse_Float()) <= 0.0)
  4166.            {
  4167.              Error("Radiosity low error factor must be a positive number.");
  4168.            }
  4169.          END_CASE
  4170.  
  4171.          CASE (MINIMUM_REUSE_TOKEN)
  4172.            if (( opts.Radiosity_Min_Reuse = Parse_Float()) < 0.0)
  4173.            {
  4174.               Error("Radiosity min reuse can not be a negative number.");
  4175.            }
  4176.          END_CASE
  4177.  
  4178.          CASE (NEAREST_COUNT_TOKEN)
  4179.            opts.Radiosity_Nearest_Count = (int)Parse_Float();
  4180.            if (( opts.Radiosity_Nearest_Count < 1) ||
  4181.                ( opts.Radiosity_Nearest_Count > MAX_NEAREST_COUNT))
  4182.            {
  4183.               Error("Radiosity nearest count must be a value from 1 to %ld.", (long)MAX_NEAREST_COUNT);
  4184.            }
  4185.          END_CASE
  4186.  
  4187.          CASE (RECURSION_LIMIT_TOKEN)
  4188.            if (( opts.Radiosity_Recursion_Limit = (int)Parse_Float()) <= 0)
  4189.            {
  4190.               Error("Radiosity recursion limit must be a positive number.");
  4191.            }
  4192.          END_CASE
  4193.  
  4194.          OTHERWISE
  4195.            UNGET
  4196.            EXIT
  4197.          END_CASE
  4198.        END_EXPECT
  4199.        Parse_End();
  4200.      END_CASE
  4201.  
  4202.      CASE (HF_GRAY_16_TOKEN)
  4203.        if (Allow_Float(1.0)>EPSILON)     
  4204.        {
  4205.          opts.Options |= HF_GRAY_16;
  4206.          opts.PaletteOption = GREY;        /* Force gray scale preview */
  4207.          Output_File_Handle->file_type = HF_FTYPE;
  4208.        }
  4209.      END_CASE
  4210.  
  4211.      OTHERWISE
  4212.        UNGET
  4213.        EXIT
  4214.      END_CASE
  4215.    END_EXPECT
  4216.    Parse_End();
  4217. }
  4218.  
  4219.  
  4220.  
  4221. /*****************************************************************************
  4222. *
  4223. * FUNCTION
  4224. *
  4225. * INPUT
  4226. *   
  4227. * OUTPUT
  4228. *   
  4229. * RETURNS
  4230. *   
  4231. * AUTHOR
  4232. *   
  4233. * DESCRIPTION
  4234. *
  4235. * CHANGES
  4236. *
  4237. ******************************************************************************/
  4238.  
  4239. void Destroy_Frame()
  4240. {
  4241.     FOG *Fog, *Next_Fog;
  4242.     RAINBOW *Rainbow, *Next_Rainbow;
  4243.  
  4244.     Destroy_Camera (Frame.Camera); Frame.Camera=NULL;
  4245.  
  4246.     /* Destroy fogs. [DB 12/94] */
  4247.  
  4248.     for (Fog = Frame.Fog; Fog != NULL;)
  4249.     {
  4250.       Next_Fog = Fog->Next;
  4251.  
  4252.       Destroy_Fog(Fog);
  4253.  
  4254.       Fog = Next_Fog;
  4255.     }
  4256.     
  4257.     Frame.Fog = NULL;
  4258.  
  4259.     /* Destroy rainbows. [DB 12/94] */
  4260.  
  4261.     for (Rainbow = Frame.Rainbow; Rainbow != NULL;)
  4262.     {
  4263.       Next_Rainbow = Rainbow->Next;
  4264.  
  4265.       Destroy_Rainbow(Rainbow);
  4266.  
  4267.       Rainbow = Next_Rainbow;
  4268.     }
  4269.  
  4270.     Frame.Rainbow = NULL;
  4271.  
  4272.     /* Destroy skysphere. [DB 12/94] */
  4273.  
  4274.     Destroy_Skysphere(Frame.Skysphere);
  4275.  
  4276.     Frame.Skysphere = NULL;
  4277.  
  4278.     /* Destroy atmosphere. [DB 1/95] */
  4279.  
  4280.     Destroy_Atmosphere(Frame.Atmosphere);
  4281.  
  4282.     Frame.Atmosphere = NULL;
  4283.  
  4284.     if (Frame.Objects != NULL) {
  4285.        Destroy_Object (Frame.Objects);
  4286.        Frame.Objects = NULL;
  4287.        Frame.Light_Sources = NULL;
  4288.     }
  4289. }
  4290.  
  4291.  
  4292.  
  4293.  
  4294. /*****************************************************************************
  4295. *
  4296. * FUNCTION
  4297. *
  4298. * INPUT
  4299. *
  4300. * OUTPUT
  4301. *
  4302. * RETURNS
  4303. *
  4304. * AUTHOR
  4305. *
  4306. * DESCRIPTION
  4307. *
  4308. * CHANGES
  4309. *
  4310. ******************************************************************************/
  4311.  
  4312. static void Parse_Camera (Camera_Ptr)
  4313. CAMERA **Camera_Ptr;
  4314. {
  4315.    int i;
  4316.    DBL Direction_Length = 1.0, Up_Length, Right_Length, Handedness;
  4317.    DBL k1, k2, k3;
  4318.    VECTOR Local_Vector;
  4319.    MATRIX Local_Matrix;
  4320.    TRANSFORM Local_Trans;
  4321.    CAMERA *New;
  4322.  
  4323.    Parse_Begin ();
  4324.  
  4325.    EXPECT
  4326.      CASE (CAMERA_ID_TOKEN)
  4327.        Destroy_Camera(*Camera_Ptr);
  4328.        *Camera_Ptr = Copy_Camera ((CAMERA *) Token.Constant_Data);
  4329.        EXIT
  4330.      END_CASE
  4331.  
  4332.      OTHERWISE
  4333.        UNGET
  4334.        EXIT
  4335.      END_CASE
  4336.    END_EXPECT
  4337.  
  4338.    New = *Camera_Ptr;
  4339.  
  4340.    EXPECT
  4341.      /* Get camera type. [DB 7/94] */
  4342.  
  4343.      CASE (PERSPECTIVE_TOKEN)
  4344.        New->Type = PERSPECTIVE_CAMERA;
  4345.      END_CASE
  4346.  
  4347.      CASE (ORTHOGRAPHIC_TOKEN)
  4348.        New->Type = ORTHOGRAPHIC_CAMERA;
  4349.        /* 
  4350.         * Resize right and up vector to get the same image 
  4351.         * area as we get with the perspective camera. 
  4352.         */
  4353.        VSub(Local_Vector, New->Look_At, New->Location);
  4354.        VLength(k1, Local_Vector);
  4355.        VLength(k2, New->Direction);
  4356.        if ((k1 > EPSILON) && (k2 > EPSILON))
  4357.        {
  4358.          VScaleEq(New->Right, k1 / k2);
  4359.          VScaleEq(New->Up, k1 / k2);
  4360.        }
  4361.      END_CASE
  4362.  
  4363.      CASE (FISHEYE_TOKEN)
  4364.        New->Type = FISHEYE_CAMERA;
  4365.      END_CASE
  4366.  
  4367.      CASE (ULTRA_WIDE_ANGLE_TOKEN)
  4368.        New->Type = ULTRA_WIDE_ANGLE_CAMERA;
  4369.      END_CASE
  4370.  
  4371.      CASE (OMNIMAX_TOKEN)
  4372.        New->Type = OMNIMAX_CAMERA;
  4373.      END_CASE
  4374.  
  4375.      CASE (PANORAMIC_TOKEN)
  4376.        New->Type = PANORAMIC_CAMERA;
  4377.      END_CASE
  4378.  
  4379.      CASE (CYLINDER_TOKEN)
  4380.        i = (int)Parse_Float();
  4381.        switch (i)
  4382.        {
  4383.          case 1: New->Type = CYL_1_CAMERA; break;
  4384.          case 2: New->Type = CYL_2_CAMERA; break;
  4385.          case 3: New->Type = CYL_3_CAMERA; break;
  4386.          case 4: New->Type = CYL_4_CAMERA; break;
  4387.        }       
  4388.      END_CASE
  4389.  
  4390.      CASE (TEST_CAMERA_1_TOKEN)
  4391.        New->Type = TEST_CAMERA_1;
  4392.      END_CASE
  4393.  
  4394.      CASE (TEST_CAMERA_2_TOKEN)
  4395.        New->Type = TEST_CAMERA_2;
  4396.      END_CASE
  4397.  
  4398.      CASE (TEST_CAMERA_3_TOKEN)
  4399.        New->Type = TEST_CAMERA_3;
  4400.      END_CASE
  4401.  
  4402.      CASE (TEST_CAMERA_4_TOKEN)
  4403.        New->Type = TEST_CAMERA_4;
  4404.      END_CASE
  4405.  
  4406.      /* Read viewing angle. Scale direction vector if necessary. [DB 7/94] */
  4407.  
  4408.      CASE (ANGLE_TOKEN)
  4409.        New->Angle = Parse_Float();
  4410.  
  4411.        if (New->Angle < 0.0)
  4412.        {
  4413.          Error("Negative viewing angle.");
  4414.        }
  4415.  
  4416.        if (New->Type == PERSPECTIVE_CAMERA)
  4417.        {
  4418.          if (New->Angle >= 180.0)
  4419.          {
  4420.            Error("Viewing angle has to be smaller than 180 degrees.");
  4421.          }
  4422.  
  4423.          VNormalize(New->Direction, New->Direction);
  4424.  
  4425.          VLength (Right_Length, New->Right);
  4426.  
  4427.          Direction_Length = Right_Length / tan(New->Angle * M_PI_360)/2.0;
  4428.  
  4429.          VScaleEq(New->Direction, Direction_Length);
  4430.        }
  4431.      END_CASE
  4432.  
  4433.  
  4434.      /* Read primary ray pertubation. [DB 7/94] */
  4435.  
  4436.      CASE (TNORMAL_TOKEN)
  4437.        Parse_Begin ();
  4438.        Parse_Tnormal(&(New->Tnormal));
  4439.        Parse_End ();
  4440.      END_CASE
  4441.  
  4442.      CASE (LOCATION_TOKEN)
  4443.        Parse_Vector(New->Location);
  4444.      END_CASE
  4445.  
  4446.      CASE (DIRECTION_TOKEN)
  4447.        Parse_Vector(New->Direction);
  4448.      END_CASE
  4449.  
  4450.      CASE (UP_TOKEN)
  4451.        Parse_Vector(New->Up);
  4452.      END_CASE
  4453.  
  4454.      CASE (RIGHT_TOKEN)
  4455.        Parse_Vector(New->Right);
  4456.      END_CASE
  4457.  
  4458.      CASE (SKY_TOKEN)
  4459.        Parse_Vector(New->Sky);
  4460.      END_CASE
  4461.  
  4462.      CASE (LOOK_AT_TOKEN)
  4463.        VLength (Direction_Length, New->Direction);
  4464.        VLength (Up_Length,        New->Up);
  4465.        VLength (Right_Length,     New->Right);
  4466.        VCross  (Local_Vector,     New->Up,        New->Direction);
  4467.        VDot    (Handedness,       Local_Vector,   New->Right);
  4468.  
  4469.        Parse_Vector (New->Direction);
  4470.        Assign_Vector(New->Look_At, New->Direction);
  4471.  
  4472.        VSub          (New->Direction, New->Direction, New->Location);
  4473.  
  4474.        /* Check for zero length direction vector. */
  4475.  
  4476.        if (VSumSqr(New->Direction) < EPSILON)
  4477.        {
  4478.          Error("Camera location and look_at point must be different.\n");
  4479.        }
  4480.        
  4481.        VNormalize    (New->Direction, New->Direction);
  4482.  
  4483.        /* Save Right vector */
  4484.  
  4485.        Assign_Vector (Local_Vector, New->Right);
  4486.  
  4487.        VCross        (New->Right, New->Sky, New->Direction);
  4488.  
  4489.        /* Avoid DOMAIN error (from Terry Kanakis) */
  4490.  
  4491.        if((fabs(New->Right[X]) < EPSILON) &&
  4492.           (fabs(New->Right[Y]) < EPSILON) &&
  4493.           (fabs(New->Right[Z]) < EPSILON))
  4494.        {
  4495.          /* Restore Right vector*/
  4496.  
  4497.          Assign_Vector (New->Right, Local_Vector);
  4498.        }
  4499.  
  4500.        VNormalize (New->Right,     New->Right);
  4501.        VCross     (New->Up,        New->Direction, New->Right);
  4502.        VScale     (New->Direction, New->Direction, Direction_Length);
  4503.  
  4504.        if (Handedness > 0.0)
  4505.          VScaleEq (New->Right, Right_Length)
  4506.        else
  4507.          VScaleEq (New->Right, -Right_Length);
  4508.  
  4509.        VScaleEq(New->Up, Up_Length);
  4510.      END_CASE
  4511.  
  4512.      CASE (TRANSLATE_TOKEN)
  4513.        Parse_Vector (Local_Vector);
  4514.        Translate_Camera (New, Local_Vector);
  4515.      END_CASE
  4516.  
  4517.      CASE (ROTATE_TOKEN)
  4518.        Parse_Vector (Local_Vector);
  4519.        Rotate_Camera (New, Local_Vector);
  4520.      END_CASE
  4521.  
  4522.      CASE (SCALE_TOKEN)
  4523.        Parse_Scale_Vector (Local_Vector);
  4524.        Scale_Camera (New, Local_Vector);
  4525.      END_CASE
  4526.  
  4527.      CASE (TRANSFORM_TOKEN)
  4528.        GET(TRANSFORM_ID_TOKEN)
  4529.        Transform_Camera (New, (TRANSFORM *)Token.Constant_Data);
  4530.      END_CASE
  4531.  
  4532.      CASE (MATRIX_TOKEN)
  4533.        Parse_Matrix (Local_Matrix);
  4534.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  4535.        Transform_Camera (New, &Local_Trans);
  4536.      END_CASE
  4537.  
  4538.      /* Parse focal blur stuff. */
  4539.  
  4540.      CASE (BLUR_SAMPLES_TOKEN)
  4541.         New->Blur_Samples = Parse_Float();
  4542.         if (New->Blur_Samples <= 0)
  4543.         {
  4544.           Error("Illegal number of focal blur samples.\n");
  4545.         }
  4546.      END_CASE
  4547.  
  4548.      CASE (CONFIDENCE_TOKEN)
  4549.         k1 = Parse_Float();
  4550.         if ((k1 > 0.0) && (k1 < 1.0))
  4551.         {
  4552.           New->Confidence = k1;
  4553.         }
  4554.         else
  4555.         {
  4556.           Warn(0.0, "Illegal confidence value. Default is used.");
  4557.         }
  4558.      END_CASE
  4559.  
  4560.      CASE (VARIANCE_TOKEN)
  4561.         k1 = Parse_Float();
  4562.         if ((k1 >= 0.0) && (k1 <= 1.0))
  4563.         {
  4564.           New->Variance = k1;
  4565.         }
  4566.         else
  4567.         {
  4568.           Warn(0.0, "Illegal variance value. Default is used.");
  4569.         }
  4570.      END_CASE
  4571.  
  4572.      CASE (APERTURE_TOKEN)
  4573.         New->Aperture = Parse_Float();
  4574.      END_CASE
  4575.  
  4576.      CASE (FOCAL_POINT_TOKEN)
  4577.         Parse_Vector(Local_Vector);
  4578.         VSubEq(Local_Vector, New->Location);
  4579.         VLength (New->Focal_Distance, Local_Vector);
  4580.      END_CASE
  4581.  
  4582.      OTHERWISE
  4583.        UNGET
  4584.        EXIT
  4585.      END_CASE
  4586.    END_EXPECT
  4587.    Parse_End ();
  4588.  
  4589.    /* Make sure the focal distance hasn't been explicitly given */
  4590.    if ( New->Focal_Distance < 0.0 )
  4591.       New->Focal_Distance = Direction_Length;
  4592.    if ( New->Focal_Distance == 0.0 )
  4593.       New->Focal_Distance = 1.0;
  4594.  
  4595.    /* Print a warning message if vectors are not perpendicular. [DB 10/94] */
  4596.  
  4597.    VDot(k1, New->Right, New->Up);
  4598.    VDot(k2, New->Right, New->Direction);
  4599.    VDot(k3, New->Up, New->Direction);
  4600.  
  4601.    if ((fabs(k1) > EPSILON) || (fabs(k2) > EPSILON) || (fabs(k3) > EPSILON))
  4602.    {
  4603.      Warn(0.0, "Camera vectors are not perpendicular. "
  4604.                "Making look_at the last statement may help.");
  4605.    }
  4606. }
  4607.  
  4608.  
  4609.  
  4610. /*****************************************************************************
  4611. *
  4612. * FUNCTION
  4613. *
  4614. * INPUT
  4615. *
  4616. * OUTPUT
  4617. *
  4618. * RETURNS
  4619. *
  4620. * AUTHOR
  4621. *
  4622. * DESCRIPTION
  4623. *
  4624. * CHANGES
  4625. *
  4626. ******************************************************************************/
  4627.  
  4628. void Parse_Matrix(Matrix)
  4629. MATRIX Matrix;
  4630. {
  4631.   int i, j;
  4632.  
  4633.   EXPECT
  4634.     CASE (LEFT_ANGLE_TOKEN)
  4635.       Matrix[0][0] = Parse_Float();
  4636.       for (i = 0; i < 4; i++)
  4637.       {
  4638.         for (j = !i ? 1 : 0; j < 3; j++)
  4639.         {
  4640.           Parse_Comma();
  4641.  
  4642.           Matrix[i][j] = Parse_Float();
  4643.         }
  4644.  
  4645.         Matrix[i][3] = (i != 3 ? 0.0 : 1.0);
  4646.       }
  4647.       GET (RIGHT_ANGLE_TOKEN);
  4648.  
  4649.       /* Check to see that we aren't scaling any dimension by zero */
  4650.       for (i = 0; i < 3; i++)
  4651.       {
  4652.         if (fabs(Matrix[0][i]) < EPSILON && fabs(Matrix[1][i]) < EPSILON &&
  4653.             fabs(Matrix[2][i]) < EPSILON)
  4654.         {
  4655.           Warn(0.0,"Illegal matrix column: Scale by 0.0. Changed to 1.0.");
  4656.           Matrix[i][i] = 1.0;
  4657.         }
  4658.       }
  4659.       EXIT
  4660.     END_CASE
  4661.  
  4662.     OTHERWISE
  4663.       Parse_Error (LEFT_ANGLE_TOKEN);
  4664.     END_CASE
  4665.   END_EXPECT
  4666. }
  4667.  
  4668.  
  4669.  
  4670. /*****************************************************************************
  4671. *
  4672. * FUNCTION
  4673. *
  4674. * INPUT
  4675. *
  4676. * OUTPUT
  4677. *
  4678. * RETURNS
  4679. *
  4680. * AUTHOR
  4681. *
  4682. * DESCRIPTION
  4683. *
  4684. * CHANGES
  4685. *
  4686. ******************************************************************************/
  4687.  
  4688. static
  4689. TRANSFORM *Parse_Transform ()
  4690.   {
  4691.    MATRIX Local_Matrix;
  4692.    TRANSFORM *New, Local_Trans;
  4693.    VECTOR Local_Vector;
  4694.  
  4695.    Parse_Begin ();
  4696.    New = Create_Transform ();
  4697.  
  4698.    EXPECT
  4699.      CASE(TRANSFORM_ID_TOKEN)
  4700.        Compose_Transforms (New, (TRANSFORM *)Token.Constant_Data);
  4701.        EXIT
  4702.      END_CASE
  4703.  
  4704.      CASE (TRANSLATE_TOKEN)
  4705.        Parse_Vector (Local_Vector);
  4706.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  4707.        Compose_Transforms (New, &Local_Trans);
  4708.      END_CASE
  4709.  
  4710.      CASE (ROTATE_TOKEN)
  4711.        Parse_Vector (Local_Vector);
  4712.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  4713.        Compose_Transforms (New, &Local_Trans);
  4714.      END_CASE
  4715.  
  4716.      CASE (SCALE_TOKEN)
  4717.        Parse_Scale_Vector (Local_Vector);
  4718.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  4719.        Compose_Transforms (New, &Local_Trans);
  4720.      END_CASE
  4721.  
  4722.      CASE (MATRIX_TOKEN)
  4723.        Parse_Matrix(Local_Matrix);
  4724.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  4725.        Compose_Transforms (New, &Local_Trans);
  4726.      END_CASE
  4727.  
  4728.      OTHERWISE
  4729.        UNGET
  4730.        EXIT
  4731.      END_CASE
  4732.    END_EXPECT
  4733.  
  4734.    Parse_End ();
  4735.    return (New);
  4736.   }
  4737.  
  4738.  
  4739.  
  4740. /*****************************************************************************
  4741. *
  4742. * FUNCTION
  4743. *
  4744. * INPUT
  4745. *   
  4746. * OUTPUT
  4747. *   
  4748. * RETURNS
  4749. *   
  4750. * AUTHOR
  4751. *   
  4752. * DESCRIPTION
  4753. *
  4754. * CHANGES
  4755. *
  4756. ******************************************************************************/
  4757.  
  4758. void Parse_Declare ()
  4759.   {
  4760.   VECTOR Local_Vector;
  4761.   COLOUR *Local_Colour;
  4762.   PIGMENT *Local_Pigment;
  4763.   TNORMAL *Local_Tnormal;
  4764.   FINISH *Local_Finish;
  4765.   HALO *Local_Halo = NULL;
  4766.   TEXTURE *Local_Texture, *Temp_Texture;
  4767.   TRANSFORM *Local_Trans;
  4768.   OBJECT *Local_Object;
  4769.   CAMERA *Local_Camera;
  4770.   char *Temp_Data;
  4771.   int Previous;
  4772.  
  4773.   struct Constant_Struct *Constant_Ptr = NULL;
  4774.  
  4775.   EXPECT
  4776.     CASE (IDENTIFIER_TOKEN)
  4777.       if (++Number_Of_Constants >= Max_Constants)
  4778.       {
  4779.         if (Max_Constants >= INT_MAX/2)
  4780.         {
  4781.           Error("Too many constants declared.\n");
  4782.         }
  4783.  
  4784.         Max_Constants *= 2;
  4785.  
  4786.         Constants = (struct Constant_Struct *)POV_REALLOC(Constants, (Max_Constants+1) * sizeof(struct Constant_Struct), "constants table");
  4787.       }
  4788.  
  4789.       Constant_Ptr = &(Constants[Number_Of_Constants]);
  4790.       Constant_Ptr->Constant_Type = IDENTIFIER_TOKEN;
  4791.       EXIT
  4792.     END_CASE
  4793.  
  4794.     CASE4 (TNORMAL_ID_TOKEN, FINISH_ID_TOKEN, TEXTURE_ID_TOKEN, OBJECT_ID_TOKEN)
  4795.     CASE4 (COLOUR_MAP_ID_TOKEN, TRANSFORM_ID_TOKEN, CAMERA_ID_TOKEN, PIGMENT_ID_TOKEN)
  4796.     CASE4 (SLOPE_MAP_ID_TOKEN,NORMAL_MAP_ID_TOKEN,TEXTURE_MAP_ID_TOKEN,COLOUR_ID_TOKEN)
  4797.     CASE3 (PIGMENT_MAP_ID_TOKEN, HALO_ID_TOKEN,STRING_ID_TOKEN)
  4798.       Constant_Ptr = &(Constants[Token.Constant_Index]);
  4799.       EXIT
  4800.     END_CASE
  4801.  
  4802.     CASE2 (VECTOR_FUNCT_TOKEN, FLOAT_FUNCT_TOKEN)
  4803.       switch(Token.Function_Id)
  4804.         {
  4805.          case VECTOR_ID_TOKEN:
  4806.          case FLOAT_ID_TOKEN:
  4807.            Constant_Ptr = &(Constants[Token.Constant_Index]);
  4808.            break;
  4809.  
  4810.          default:
  4811.            Parse_Error(IDENTIFIER_TOKEN);
  4812.            break;
  4813.         }
  4814.       EXIT
  4815.     END_CASE
  4816.  
  4817.     OTHERWISE
  4818.       Parse_Error(IDENTIFIER_TOKEN);
  4819.     END_CASE
  4820.   END_EXPECT
  4821.  
  4822.   Previous = Token.Token_Id;
  4823.  
  4824.   GET (EQUALS_TOKEN);
  4825.  
  4826.   EXPECT
  4827.     CASE_COLOUR
  4828.       Local_Colour = Create_Colour();
  4829.       Ok_To_Declare = FALSE;
  4830.       Parse_Colour (*Local_Colour);
  4831.       Ok_To_Declare = TRUE;
  4832.       if (Test_Redefine(Previous,COLOUR_ID_TOKEN))
  4833.         Destroy_Colour((COLOUR *)Constant_Ptr->Constant_Data);
  4834.       Constant_Ptr->Constant_Data = (char *) Local_Colour;
  4835.       Constant_Ptr->Constant_Type = COLOUR_ID_TOKEN;
  4836.       EXIT
  4837.     END_CASE
  4838.  
  4839.     CASE_VECTOR
  4840.       Ok_To_Declare = FALSE;
  4841.       Have_Vector = FALSE;
  4842.       Parse_Vector_Float (Local_Vector);
  4843.       if (Have_Vector)
  4844.         {
  4845.          if (Test_Redefine(Previous,VECTOR_FUNCT_TOKEN))
  4846.            Destroy_Vector((VECTOR *)Constant_Ptr->Constant_Data);
  4847.          Constant_Ptr->Constant_Type = VECTOR_ID_TOKEN;
  4848.          Constant_Ptr->Constant_Data = (char *) Create_Vector();
  4849.          Assign_Vector(Constant_Ptr->Constant_Data,Local_Vector);
  4850.         }
  4851.       else
  4852.         {
  4853.          if (Test_Redefine(Previous,FLOAT_FUNCT_TOKEN))
  4854.            Destroy_Float((DBL *)Constant_Ptr->Constant_Data);
  4855.          Constant_Ptr->Constant_Type = FLOAT_ID_TOKEN;
  4856.                         Constant_Ptr->Constant_Data = (char *) Create_Float();
  4857.          *((DBL *) Constant_Ptr->Constant_Data) = Local_Vector[X];
  4858.         }
  4859.       Ok_To_Declare = TRUE;
  4860.       EXIT
  4861.     END_CASE
  4862.  
  4863.     CASE (PIGMENT_TOKEN)
  4864.       Local_Pigment = Copy_Pigment((Default_Texture->Pigment));
  4865.       Parse_Begin ();
  4866.       Parse_Pigment (&Local_Pigment);
  4867.       Parse_End ();
  4868.       if (Test_Redefine(Previous,PIGMENT_ID_TOKEN))
  4869.         Destroy_Pigment((PIGMENT *)Constant_Ptr->Constant_Data);
  4870.       Constant_Ptr->Constant_Type = PIGMENT_ID_TOKEN;
  4871.       Constant_Ptr->Constant_Data = (char *)Local_Pigment;
  4872.       EXIT
  4873.     END_CASE
  4874.  
  4875.     CASE (TNORMAL_TOKEN)
  4876.       Local_Tnormal = Copy_Tnormal((Default_Texture->Tnormal));
  4877.       Parse_Begin ();
  4878.       Parse_Tnormal (&Local_Tnormal);
  4879.       Parse_End ();
  4880.       if (Test_Redefine(Previous,TNORMAL_ID_TOKEN))
  4881.         Destroy_Tnormal((TNORMAL *)Constant_Ptr->Constant_Data);
  4882.       Constant_Ptr->Constant_Type = TNORMAL_ID_TOKEN;
  4883.       Constant_Ptr->Constant_Data = (char *) Local_Tnormal;
  4884.       EXIT
  4885.     END_CASE
  4886.  
  4887.     CASE (FINISH_TOKEN)
  4888.       Local_Finish = Copy_Finish((Default_Texture->Finish));
  4889.       Parse_Finish (&Local_Finish);
  4890.       if (Test_Redefine(Previous,FINISH_ID_TOKEN))
  4891.         Destroy_Finish((FINISH *)Constant_Ptr->Constant_Data);
  4892.       Constant_Ptr->Constant_Type = FINISH_ID_TOKEN;
  4893.       Constant_Ptr->Constant_Data = (char *) Local_Finish;
  4894.       EXIT
  4895.     END_CASE
  4896.  
  4897.     CASE (HALO_TOKEN)
  4898.       Local_Halo = Copy_Halo((Default_Texture->Halo));
  4899.       Parse_Halo (&Local_Halo);
  4900.       if (Test_Redefine(Previous,HALO_ID_TOKEN))
  4901.         Destroy_Halo((HALO *)Constant_Ptr->Constant_Data);
  4902.       Constant_Ptr->Constant_Type = HALO_ID_TOKEN;
  4903.       Constant_Ptr->Constant_Data = (char *) Local_Halo;
  4904.       EXIT
  4905.     END_CASE
  4906.  
  4907.     CASE (CAMERA_TOKEN)
  4908.       Local_Camera = Copy_Camera(Default_Camera);
  4909.       Parse_Camera (&Local_Camera);
  4910.       if (Test_Redefine(Previous,CAMERA_ID_TOKEN))
  4911.         Destroy_Camera((CAMERA *)Constant_Ptr->Constant_Data);
  4912.       Constant_Ptr->Constant_Type = CAMERA_ID_TOKEN;
  4913.       Constant_Ptr->Constant_Data = (char *) Local_Camera;
  4914.       EXIT
  4915.     END_CASE
  4916.  
  4917.     CASE (TEXTURE_TOKEN)
  4918.       Parse_Begin ();
  4919.       Local_Texture = Parse_Texture ();
  4920.       Parse_End ();
  4921.       Temp_Texture=NULL;
  4922.       Link_Textures(&Temp_Texture, Local_Texture);
  4923.       Ok_To_Declare = FALSE;
  4924.       EXPECT
  4925.         CASE (TEXTURE_TOKEN)
  4926.           Parse_Begin ();
  4927.           Local_Texture = Parse_Texture ();
  4928.           Parse_End ();
  4929.           Link_Textures(&Temp_Texture, Local_Texture);
  4930.         END_CASE
  4931.  
  4932.         OTHERWISE
  4933.           UNGET
  4934.           EXIT
  4935.         END_CASE
  4936.       END_EXPECT
  4937.  
  4938.       if (Test_Redefine(Previous,TEXTURE_ID_TOKEN))
  4939.       {
  4940.         Destroy_Textures((TEXTURE *)Constant_Ptr->Constant_Data);
  4941.       }
  4942.       Constant_Ptr->Constant_Type = TEXTURE_ID_TOKEN;
  4943.       Constant_Ptr->Constant_Data = (char *)Temp_Texture;
  4944.       Ok_To_Declare = TRUE;
  4945.       EXIT
  4946.     END_CASE
  4947.  
  4948.     CASE (COLOUR_MAP_TOKEN)
  4949.       Temp_Data=(char *) Parse_Colour_Map ();
  4950.       if (Test_Redefine(Previous,COLOUR_MAP_ID_TOKEN))
  4951.         Destroy_Blend_Map((BLEND_MAP *)Constant_Ptr->Constant_Data);
  4952.       Constant_Ptr->Constant_Type = COLOUR_MAP_ID_TOKEN;
  4953.       Constant_Ptr->Constant_Data = Temp_Data;
  4954.       EXIT
  4955.     END_CASE
  4956.  
  4957.     CASE (PIGMENT_MAP_TOKEN)
  4958.       Temp_Data = (char *) Parse_Blend_Map (PIGMENT_TYPE,NO_PATTERN);
  4959.       if (Test_Redefine(Previous,PIGMENT_MAP_ID_TOKEN))
  4960.         Destroy_Blend_Map((BLEND_MAP *)Constant_Ptr->Constant_Data);
  4961.       Constant_Ptr->Constant_Type = PIGMENT_MAP_ID_TOKEN;
  4962.       Constant_Ptr->Constant_Data = Temp_Data;
  4963.       EXIT
  4964.     END_CASE
  4965.  
  4966.     CASE (SLOPE_MAP_TOKEN)
  4967.       Temp_Data = (char *) Parse_Blend_Map (SLOPE_TYPE,NO_PATTERN);
  4968.       Constant_Ptr->Constant_Type = SLOPE_MAP_ID_TOKEN;
  4969.       if (Test_Redefine(Previous,SLOPE_MAP_ID_TOKEN))
  4970.         Destroy_Blend_Map((BLEND_MAP *)Constant_Ptr->Constant_Data);
  4971.       Constant_Ptr->Constant_Data = Temp_Data;
  4972.       EXIT
  4973.     END_CASE
  4974.  
  4975.     CASE (TEXTURE_MAP_TOKEN)
  4976.       Temp_Data = (char *) Parse_Blend_Map (TEXTURE_TYPE,NO_PATTERN);
  4977.       Constant_Ptr->Constant_Type = TEXTURE_MAP_ID_TOKEN;
  4978.       if (Test_Redefine(Previous,TEXTURE_MAP_ID_TOKEN))
  4979.         Destroy_Blend_Map((BLEND_MAP *)Constant_Ptr->Constant_Data);
  4980.       Constant_Ptr->Constant_Data = Temp_Data;
  4981.       EXIT
  4982.     END_CASE
  4983.  
  4984.     CASE (NORMAL_MAP_TOKEN)
  4985.       Temp_Data= (char *) Parse_Blend_Map (NORMAL_TYPE,NO_PATTERN);
  4986.       Constant_Ptr->Constant_Type = NORMAL_MAP_ID_TOKEN;
  4987.       if (Test_Redefine(Previous,NORMAL_MAP_ID_TOKEN))
  4988.         Destroy_Blend_Map((BLEND_MAP *)Constant_Ptr->Constant_Data);
  4989.       Constant_Ptr->Constant_Data = Temp_Data;
  4990.       EXIT
  4991.     END_CASE
  4992.  
  4993.     CASE (RAINBOW_TOKEN)
  4994.       Temp_Data= (char *) Parse_Rainbow();
  4995.       Constant_Ptr->Constant_Type = RAINBOW_ID_TOKEN;
  4996.       if (Test_Redefine(Previous,RAINBOW_ID_TOKEN))
  4997.         Destroy_Rainbow((RAINBOW *)Constant_Ptr->Constant_Data);
  4998.       Constant_Ptr->Constant_Data = Temp_Data;
  4999.       EXIT
  5000.     END_CASE
  5001.  
  5002.     CASE (FOG_TOKEN)
  5003.       Temp_Data= (char *) Parse_Fog();
  5004.       if (Test_Redefine(Previous,FOG_ID_TOKEN))
  5005.         Destroy_Fog((FOG *)Constant_Ptr->Constant_Data);
  5006.       Constant_Ptr->Constant_Data = Temp_Data;
  5007.       Constant_Ptr->Constant_Type = FOG_ID_TOKEN;
  5008.       EXIT
  5009.     END_CASE
  5010.  
  5011.     CASE (ATMOSPHERE_TOKEN)
  5012.       Temp_Data= (char *) Parse_Atmosphere();
  5013.       if (Test_Redefine(Previous,ATMOSPHERE_ID_TOKEN))
  5014.         Destroy_Atmosphere((ATMOSPHERE *)Constant_Ptr->Constant_Data);
  5015.       Constant_Ptr->Constant_Data = Temp_Data;
  5016.       Constant_Ptr->Constant_Type = ATMOSPHERE_ID_TOKEN;
  5017.       EXIT
  5018.     END_CASE
  5019.  
  5020.     CASE (SKYSPHERE_TOKEN)
  5021.       Temp_Data= (char *) Parse_Skysphere();
  5022.       if (Test_Redefine(Previous,SKYSPHERE_ID_TOKEN))
  5023.         Destroy_Skysphere((SKYSPHERE *)Constant_Ptr->Constant_Data);
  5024.       Constant_Ptr->Constant_Data = Temp_Data;
  5025.       Constant_Ptr->Constant_Type = SKYSPHERE_ID_TOKEN;
  5026.       EXIT
  5027.     END_CASE
  5028.  
  5029.     CASE (TRANSFORM_TOKEN)
  5030.       Local_Trans = Parse_Transform ();
  5031.       if (Test_Redefine(Previous,TRANSFORM_ID_TOKEN))
  5032.         Destroy_Transform((TRANSFORM *)Constant_Ptr->Constant_Data);
  5033.       Constant_Ptr->Constant_Type = TRANSFORM_ID_TOKEN;
  5034.       Constant_Ptr->Constant_Data = (char *) Local_Trans;
  5035.       EXIT
  5036.     END_CASE
  5037.  
  5038.     CASE4 (STRING_LITERAL_TOKEN,CHR_TOKEN,SUBSTR_TOKEN,STR_TOKEN)
  5039.     CASE4 (CONCAT_TOKEN,STRUPR_TOKEN,STRLWR_TOKEN,STRING_ID_TOKEN)
  5040.       UNGET
  5041.       Temp_Data= Parse_String();
  5042.       if (Test_Redefine(Previous,STRING_ID_TOKEN))
  5043.         POV_FREE(Constant_Ptr->Constant_Data);
  5044.       Constant_Ptr->Constant_Type = STRING_ID_TOKEN;
  5045.       Constant_Ptr->Constant_Data = Temp_Data;
  5046.       EXIT
  5047.     END_CASE
  5048.  
  5049.     OTHERWISE
  5050.       UNGET
  5051.       Local_Object = Parse_Object ();
  5052.       if (Test_Redefine(Previous,OBJECT_ID_TOKEN))
  5053.         Destroy_Object((OBJECT *)Constant_Ptr->Constant_Data);
  5054.       Constant_Ptr->Constant_Type = OBJECT_ID_TOKEN;
  5055.       Constant_Ptr->Constant_Data = (char *) Local_Object;
  5056.       EXIT
  5057.     END_CASE
  5058.  
  5059.   END_EXPECT
  5060. }
  5061.  
  5062.  
  5063.  
  5064. /*****************************************************************************
  5065. *
  5066. * FUNCTION
  5067. *
  5068. * INPUT
  5069. *   
  5070. * OUTPUT
  5071. *   
  5072. * RETURNS
  5073. *   
  5074. * AUTHOR
  5075. *   
  5076. * DESCRIPTION
  5077. *
  5078. * CHANGES
  5079. *
  5080. ******************************************************************************/
  5081.  
  5082. static void Link (New_Object, Field, Old_Object_List)
  5083.   OBJECT *New_Object, **Field, **Old_Object_List;
  5084.   {
  5085.   *Field = *Old_Object_List;
  5086.   *Old_Object_List = New_Object;
  5087.   }
  5088.  
  5089.  
  5090.  
  5091. /*****************************************************************************
  5092. *
  5093. * FUNCTION
  5094. *
  5095. * INPUT
  5096. *
  5097. * OUTPUT
  5098. *   
  5099. * RETURNS
  5100. *   
  5101. * AUTHOR
  5102. *   
  5103. * DESCRIPTION
  5104. *
  5105. * CHANGES
  5106. *
  5107. ******************************************************************************/
  5108.  
  5109. void Link_Textures (Old_Textures, New_Textures)
  5110.   TEXTURE **Old_Textures;
  5111.   TEXTURE  *New_Textures;
  5112.   {
  5113.    TEXTURE *Layer;
  5114.    
  5115.    if (New_Textures == NULL)
  5116.      return;
  5117.  
  5118.    if ((*Old_Textures) != NULL)
  5119.    {
  5120.       if ((*Old_Textures)->Type != PLAIN_PATTERN) 
  5121.       {
  5122.          Error("Cannot layer over a patterned texture.\n");
  5123.       }
  5124.    }
  5125.    for (Layer = New_Textures ;
  5126.         Layer->Next != NULL ;
  5127.         Layer = (TEXTURE *)Layer->Next)
  5128.      {}
  5129.  
  5130.    Layer->Next = (TPATTERN *)*Old_Textures;
  5131.    *Old_Textures = New_Textures;
  5132.  
  5133.    if ((New_Textures->Type != PLAIN_PATTERN) && (New_Textures->Next != NULL))
  5134.    {
  5135.       Error("Cannot layer a patterned texture over another.\n");
  5136.    }
  5137.   }
  5138.  
  5139.  
  5140.  
  5141. /*****************************************************************************
  5142. *
  5143. * FUNCTION
  5144. *
  5145. * INPUT
  5146. *
  5147. * OUTPUT
  5148. *
  5149. * RETURNS
  5150. *
  5151. * AUTHOR
  5152. *
  5153. * DESCRIPTION
  5154. *
  5155. * CHANGES
  5156. *
  5157. ******************************************************************************/
  5158.  
  5159. static
  5160. char *Get_Token_String (Token_Id)
  5161.   TOKEN Token_Id;
  5162.   {
  5163.   register int i;
  5164.  
  5165.   for (i = 0 ; i < LAST_TOKEN ; i++)
  5166.      if (Reserved_Words[i].Token_Number == Token_Id)
  5167.         return (Reserved_Words[i].Token_Name);
  5168.   return ("");
  5169.   }
  5170.  
  5171.  
  5172.  
  5173. /*****************************************************************************
  5174. *
  5175. * FUNCTION
  5176. *
  5177. * INPUT
  5178. *
  5179. * OUTPUT
  5180. *
  5181. * RETURNS
  5182. *
  5183. * AUTHOR
  5184. *
  5185. * DESCRIPTION
  5186. *
  5187. * CHANGES
  5188. *
  5189. ******************************************************************************/
  5190.  
  5191. static int Test_Redefine(Previous,a)
  5192.   int Previous;
  5193.   int a;
  5194.   {
  5195.   char *old, *new;
  5196.  
  5197.   if (Previous == IDENTIFIER_TOKEN)
  5198.     return (FALSE);
  5199.   if (Previous != a)
  5200.     {old = Get_Token_String (Previous);
  5201.      new = Get_Token_String (a);
  5202.      Error ("Attempted to redefine %s as %s.", old, new);
  5203.     }
  5204.   return (TRUE);
  5205.   }
  5206.  
  5207.  
  5208.  
  5209. /*****************************************************************************
  5210. *
  5211. * FUNCTION
  5212. *
  5213. * INPUT
  5214. *
  5215. * OUTPUT
  5216. *
  5217. * RETURNS
  5218. *
  5219. * AUTHOR
  5220. *
  5221. * DESCRIPTION
  5222. *
  5223. * CHANGES
  5224. *
  5225. ******************************************************************************/
  5226.  
  5227. void Parse_Error (Token_Id)
  5228.   TOKEN Token_Id;
  5229.   {
  5230.   char *expected;
  5231.  
  5232.   expected = Get_Token_String (Token_Id);
  5233.   Parse_Error_Str(expected);
  5234.   }
  5235.  
  5236.  
  5237.  
  5238. /*****************************************************************************
  5239. *
  5240. * FUNCTION
  5241. *
  5242. * INPUT
  5243. *
  5244. * OUTPUT
  5245. *
  5246. * RETURNS
  5247. *
  5248. * AUTHOR
  5249. *
  5250. * DESCRIPTION
  5251. *
  5252. * CHANGES
  5253. *
  5254. ******************************************************************************/
  5255.  
  5256. void Parse_Error_Str (str)
  5257.   char *str;
  5258.   {
  5259.    Where_Error ();
  5260.    Error_Line("%s expected but", str);
  5261.    Found_Instead ();
  5262.   }
  5263.  
  5264.  
  5265.  
  5266. /*****************************************************************************
  5267. *
  5268. * FUNCTION
  5269. *
  5270. * INPUT
  5271. *
  5272. * OUTPUT
  5273. *
  5274. * RETURNS
  5275. *
  5276. * AUTHOR
  5277. *
  5278. * DESCRIPTION
  5279. *
  5280. * CHANGES
  5281. *
  5282. ******************************************************************************/
  5283.  
  5284. static void Found_Instead ()
  5285. {
  5286.   char *found;
  5287.   
  5288.   Stage=STAGE_FOUND_INSTEAD;
  5289.  
  5290.   switch(Token.Token_Id)
  5291.   {
  5292.     case IDENTIFIER_TOKEN:
  5293.       Error (" undeclared identifier '%s' found instead.\n", Token.Token_String);
  5294.       break;
  5295.       
  5296.     case VECTOR_FUNCT_TOKEN:
  5297.       found = Get_Token_String (Token.Function_Id);
  5298.       Error (" vector function '%s' found instead.\n", found);
  5299.       break;
  5300.       
  5301.     case FLOAT_FUNCT_TOKEN:
  5302.       found = Get_Token_String (Token.Function_Id);
  5303.       Error (" float function '%s' found instead.\n", found);
  5304.       break;
  5305.  
  5306.     case COLOUR_KEY_TOKEN:
  5307.       found = Get_Token_String (Token.Function_Id);
  5308.       Error (" color keyword '%s' found instead.\n", found);
  5309.       break;
  5310.  
  5311.     default:
  5312.       found = Get_Token_String (Token.Token_Id);
  5313.       Error (" %s found instead.\n", found);
  5314.   }
  5315. }
  5316.   
  5317.  
  5318.  
  5319. /*****************************************************************************
  5320. *
  5321. * FUNCTION
  5322. *
  5323. * INPUT
  5324. *
  5325. * OUTPUT
  5326. *
  5327. * RETURNS
  5328. *
  5329. * AUTHOR
  5330. *
  5331. * DESCRIPTION
  5332. *
  5333. * CHANGES
  5334. *
  5335. ******************************************************************************/
  5336.  
  5337. void Warn_State (Token_Id,Type)
  5338.   TOKEN Token_Id, Type;
  5339.   {
  5340.   char *found;
  5341.   char *should;
  5342.  
  5343.   found = Get_Token_String (Token_Id);
  5344.   should = Get_Token_String (Type);
  5345.   Warning (1.5, "%s:%d: warning: Found %s that should be in %s statement.\n",
  5346.            Token.Filename, Token.Token_Line_No+1, found, should);
  5347.   }
  5348.  
  5349.  
  5350.  
  5351. /*****************************************************************************
  5352. *
  5353. * FUNCTION
  5354. *
  5355. * INPUT
  5356. *
  5357. * OUTPUT
  5358. *
  5359. * RETURNS
  5360. *
  5361. * AUTHOR
  5362. *
  5363. * DESCRIPTION
  5364. *
  5365. * CHANGES
  5366. *
  5367. ******************************************************************************/
  5368.  
  5369. void Warn (Level, str)
  5370.   DBL Level;
  5371.   char *str;
  5372.   {
  5373.   if (opts.Language_Version < Level)
  5374.     return;
  5375.  
  5376.   Warning(Level, "%s:%d: warning: %s\n", Token.Filename, Token.Token_Line_No+1, str);
  5377.   }
  5378.  
  5379.  
  5380.  
  5381. /*****************************************************************************
  5382. *
  5383. * FUNCTION
  5384. *
  5385. * INPUT
  5386. *
  5387. * OUTPUT
  5388. *
  5389. * RETURNS
  5390. *
  5391. * AUTHOR
  5392. *
  5393. * DESCRIPTION
  5394. *
  5395. * CHANGES
  5396. *
  5397. ******************************************************************************/
  5398.  
  5399. void MAError (str,size)
  5400.   char *str;
  5401.   size_t size;
  5402.   {
  5403.   Error ("Out of memory.  Cannot allocate %ld bytes for %s.\n",size,str);
  5404.   }
  5405.  
  5406.  
  5407.  
  5408. /*****************************************************************************
  5409. *
  5410. * FUNCTION
  5411. *
  5412. * INPUT
  5413. *
  5414. * OUTPUT
  5415. *
  5416. * RETURNS
  5417. *
  5418. * AUTHOR
  5419. *
  5420. * DESCRIPTION
  5421. *
  5422. * CHANGES
  5423. *
  5424. ******************************************************************************/
  5425.  
  5426. /* Write a token out to the token file */
  5427.  
  5428. void Write_Token (Token_Id, Data_File)
  5429.   TOKEN Token_Id;
  5430.   DATA_FILE *Data_File;
  5431.  
  5432.   {
  5433.    Token.Token_Line_No = Data_File->Line_Number;
  5434.    Token.Filename = Data_File->Filename;
  5435.    Token.Token_String = String;
  5436.    Token.Constant_Data = NULL;
  5437.    Token.Token_Id = Token_Id;
  5438.  
  5439.    Token.Constant_Index = (int) Token.Token_Id - (int) LAST_TOKEN;
  5440.  
  5441.    if (Token.Constant_Index >= 0)
  5442.    {
  5443.       if (Token.Constant_Index <= Number_Of_Constants)
  5444.       {
  5445.         Token.Constant_Data = Constants[Token.Constant_Index].Constant_Data;
  5446.         Token.Token_Id=Constants[Token.Constant_Index].Constant_Type;
  5447.       }
  5448.       else 
  5449.       {
  5450.          Token.Token_Id = IDENTIFIER_TOKEN;
  5451.       }
  5452.    }
  5453.  
  5454.    Token.Function_Id = Token.Token_Id;
  5455.    if (Token.Token_Id < FLOAT_FUNCT_TOKEN)
  5456.      Token.Token_Id = FLOAT_FUNCT_TOKEN;
  5457.    else
  5458.      if (Token.Token_Id < VECTOR_FUNCT_TOKEN)
  5459.        Token.Token_Id = VECTOR_FUNCT_TOKEN;
  5460.      else
  5461.        if (Token.Token_Id < COLOUR_KEY_TOKEN)
  5462.          Token.Token_Id = COLOUR_KEY_TOKEN;
  5463.   }
  5464.  
  5465.  
  5466.  
  5467. /*****************************************************************************
  5468. *
  5469. * FUNCTION
  5470. *
  5471. * INPUT
  5472. *
  5473. * OUTPUT
  5474. *
  5475. * RETURNS
  5476. *
  5477. * AUTHOR
  5478. *
  5479. * DESCRIPTION
  5480. *
  5481. * CHANGES
  5482. *
  5483. ******************************************************************************/
  5484.  
  5485. static void Post_Process (Object,Parent)
  5486. OBJECT *Object, *Parent;
  5487. {
  5488.   DBL Volume;
  5489.   OBJECT *Sib;
  5490.  
  5491.   if (Object == NULL)
  5492.     return;
  5493.  
  5494.   if (Parent != NULL)
  5495.   {
  5496.     if (Object->Texture == NULL)
  5497.       Object->Texture = Copy_Texture_Pointer (Parent->Texture);
  5498.  
  5499. /*
  5500.     else
  5501.       if (Parent->Texture != NULL)
  5502.       {
  5503.         Local_Texture = Copy_Textures (Parent->Texture);
  5504.         Link_Textures (&(Object->Texture), Local_Texture);
  5505.       }
  5506. */ /* Removed for backward compat with 1.0.  May put back in. CEY 12/92 */
  5507.  
  5508.     if (Test_Flag(Parent, NO_SHADOW_FLAG))
  5509.       Set_Flag(Object, NO_SHADOW_FLAG);
  5510.   }
  5511.  
  5512.   if ((Object->Texture == NULL) &&
  5513.       !(Object->Type & TEXTURED_OBJECT) &&
  5514.       !(Object->Type & LIGHT_SOURCE_OBJECT))
  5515.     Object->Texture = Copy_Textures(Default_Texture);
  5516.  
  5517.   if (Object->Type & COMPOUND_OBJECT)
  5518.   {
  5519.     if (Object->Type & LIGHT_SOURCE_OBJECT)
  5520.     {
  5521.        ((LIGHT_SOURCE *)Object)->Next_Light_Source = Frame.Light_Sources;
  5522.        Frame.Light_Sources = (LIGHT_SOURCE *)Object;
  5523.        Frame.Number_Of_Light_Sources++;
  5524.     }
  5525.  
  5526.     for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  5527.       Post_Process(Sib, Object);
  5528.   }
  5529.   else
  5530.   {
  5531.     if (Object->Texture == NULL)
  5532.       Object->Texture = Copy_Textures(Default_Texture);
  5533.  
  5534.     if (Object->Texture->Type == PLAIN_PATTERN)
  5535.       if (Object->Texture->Tnormal != NULL)
  5536.         Object->Type |= DOUBLE_ILLUMINATE;
  5537.   }
  5538.  
  5539.   Post_Textures (Object->Texture);
  5540.  
  5541.   /* Test wether the object is finite or infinite. [DB 9/94] */
  5542.  
  5543.   BOUNDS_VOLUME(Volume, Object->BBox);
  5544.  
  5545.   if (Volume > INFINITE_VOLUME)
  5546.   {
  5547.     Set_Flag(Object, INFINITE_FLAG);
  5548.   }
  5549.  
  5550.   /* Test wether the object is opaque or not. [DB 8/94] */
  5551.  
  5552.   /*
  5553.    * Blobs and meshes have to be handled speratly because
  5554.    * of the multiple textures.
  5555.    */
  5556.  
  5557.   if ((Object->Methods != &Blob_Methods) &&
  5558.       (Object->Methods != &Mesh_Methods) &&
  5559.       (Test_Opacity(Object->Texture)))
  5560.   {
  5561.     Set_Flag(Object, OPAQUE_FLAG);
  5562.   }
  5563.  
  5564.   if (Object->Methods == &Blob_Methods)
  5565.   {
  5566.     Test_Blob_Opacity((BLOB *)Object);
  5567.   }
  5568.  
  5569.   if (Object->Methods == &Mesh_Methods)
  5570.   {
  5571.     Test_Mesh_Opacity((MESH *)Object);
  5572.   }
  5573. }
  5574.  
  5575.  
  5576.  
  5577. /*****************************************************************************
  5578. *
  5579. * FUNCTION
  5580. *
  5581. * INPUT
  5582. *
  5583. * OUTPUT
  5584. *
  5585. * RETURNS
  5586. *
  5587. * AUTHOR
  5588. *
  5589. * DESCRIPTION
  5590. *
  5591. * CHANGES
  5592. *
  5593. ******************************************************************************/
  5594.  
  5595. static void Destroy_Constants ()
  5596.   {
  5597.    int i;
  5598.    char *Ptr;
  5599.  
  5600.    for (i=1; i <= Number_Of_Constants; i++)
  5601.      {
  5602.       Ptr = Constants[i].Constant_Data;
  5603.       switch (Constants[i].Constant_Type)
  5604.         {
  5605.          case COLOUR_ID_TOKEN:
  5606.            Destroy_Colour((COLOUR *)Ptr);
  5607.            break;
  5608.          case VECTOR_ID_TOKEN:
  5609.            Destroy_Vector((VECTOR *)Ptr);
  5610.            break;
  5611.          case FLOAT_ID_TOKEN:
  5612.            Destroy_Float((DBL *)Ptr);
  5613.            break;
  5614.          case PIGMENT_ID_TOKEN:
  5615.            Destroy_Pigment((PIGMENT *)Ptr);
  5616.            break;
  5617.          case TNORMAL_ID_TOKEN:
  5618.            Destroy_Tnormal((TNORMAL *)Ptr);
  5619.            break;
  5620.          case FINISH_ID_TOKEN:
  5621.            Destroy_Finish((FINISH *)Ptr);
  5622.            break;
  5623.          case HALO_ID_TOKEN:
  5624.            Destroy_Halo((HALO *)Ptr);
  5625.            break;
  5626.          case TEXTURE_ID_TOKEN:
  5627.            Destroy_Textures((TEXTURE *)Ptr);
  5628.            break;
  5629.          case OBJECT_ID_TOKEN:
  5630.            Destroy_Object((OBJECT *)Ptr);
  5631.            break;
  5632.          case COLOUR_MAP_ID_TOKEN:
  5633.          case PIGMENT_MAP_ID_TOKEN:
  5634.          case SLOPE_MAP_ID_TOKEN:
  5635.          case TEXTURE_MAP_ID_TOKEN:
  5636.          case NORMAL_MAP_ID_TOKEN:
  5637.            Destroy_Blend_Map((BLEND_MAP *)Ptr);
  5638.            break;
  5639.          case TRANSFORM_ID_TOKEN:
  5640.            Destroy_Transform((TRANSFORM *)Ptr);
  5641.            break;
  5642.          case CAMERA_ID_TOKEN:
  5643.            Destroy_Camera((CAMERA *)Ptr);
  5644.            break;
  5645.          case RAINBOW_ID_TOKEN:
  5646.            Destroy_Rainbow((RAINBOW *)Ptr);
  5647.            break;
  5648.          case FOG_ID_TOKEN:
  5649.            Destroy_Fog((FOG *)Ptr);
  5650.            break;
  5651.          case SKYSPHERE_ID_TOKEN:
  5652.            Destroy_Skysphere((SKYSPHERE *)Ptr);
  5653.            break;
  5654.          case ATMOSPHERE_ID_TOKEN:
  5655.            Destroy_Atmosphere((ATMOSPHERE *)Ptr);
  5656.            break;
  5657.          case STRING_ID_TOKEN:
  5658.            POV_FREE(Ptr);
  5659.            break;
  5660.         }
  5661.      }
  5662.  
  5663.      POV_FREE(Constants);
  5664.   }
  5665.  
  5666. /*****************************************************************************
  5667. *
  5668. * FUNCTION
  5669. *
  5670. *   Link_To_Frame
  5671. *
  5672. * INPUT
  5673. *
  5674. *   Object - Pointer to object
  5675. *   
  5676. * OUTPUT
  5677. *
  5678. *   Object
  5679. *   
  5680. * RETURNS
  5681. *   
  5682. * AUTHOR
  5683. *
  5684. *   POV-Ray Team
  5685. *   
  5686. * DESCRIPTION
  5687. *
  5688. *   -
  5689. *
  5690. * CHANGES
  5691. *
  5692. *   Sep 1994 : Added optional splitting of bounded unions if children are
  5693. *              finite. Added removing of unnecessary bounding. [DB]
  5694. *
  5695. ******************************************************************************/
  5696.  
  5697. static void Link_To_Frame(Object)
  5698. OBJECT *Object;
  5699. {
  5700.   int finite;
  5701.   DBL Volume;
  5702.   OBJECT *This_Sib, *Next_Sib;
  5703.  
  5704.   if (Object == NULL)           /* patches a memory addressing error jdm mar/95 */
  5705.     return;
  5706.  
  5707.   /* Remove bounding object if object is cheap to intersect. [DB 8/94]  */
  5708.  
  5709.   if ((opts.Options & REMOVE_BOUNDS) && (Object->Bound != NULL))
  5710.   {
  5711.     if ((Object->Methods != &CSG_Union_Methods)        &&
  5712.         (Object->Methods != &CSG_Intersection_Methods) &&
  5713.         (Object->Methods != &CSG_Merge_Methods)        &&
  5714.         (Object->Methods != &Poly_Methods)             &&
  5715.         (Object->Methods != &TTF_Methods))
  5716.     {
  5717.       /* Destroy only, if bounding object is not used as clipping object. */
  5718.  
  5719.       if (Object->Bound != Object->Clip)
  5720.       {
  5721.         Destroy_Object(Object->Bound);
  5722.       }
  5723.  
  5724.       Object->Bound = NULL;
  5725.  
  5726.       Warn(0.0, "Unnecessary bounding object removed.");
  5727.     }
  5728.   }
  5729.  
  5730.   /*
  5731.    * Link the object to the frame if it's not a CSG union object,
  5732.    * if it's clipped or if bounding slabs aren't used.
  5733.    */
  5734.  
  5735.   if ((Object->Methods != &CSG_Union_Methods) ||
  5736.       (Object->Clip != NULL) ||
  5737.       (!opts.Use_Slabs))
  5738.   {
  5739.     Link(Object, &(Object->Sibling), &(Frame.Objects));
  5740.  
  5741.     return;
  5742.   }
  5743.  
  5744.   /*
  5745.    * [DB 8/94]
  5746.    *
  5747.    * The object is a CSG union object. It will be split if all siblings are
  5748.    * finite, i.e. the volume of the bounding box doesn't exceed a threshold.
  5749.    */
  5750.  
  5751.   if (Object->Bound != NULL)
  5752.   {
  5753.     /* Test if all siblings are finite. */
  5754.  
  5755.     finite = TRUE;
  5756.  
  5757.     for (This_Sib = ((CSG *)Object)->Children; This_Sib != NULL; This_Sib = This_Sib->Sibling)
  5758.     {
  5759.       BOUNDS_VOLUME(Volume, This_Sib->BBox);
  5760.  
  5761.       if (Volume > BOUND_HUGE)
  5762.       {
  5763.         finite = FALSE;
  5764.  
  5765.         break;
  5766.       }
  5767.     }
  5768.  
  5769.     /*
  5770.      * If the union has infinite children or splitting is not used link
  5771.      * the union to the frame.
  5772.      */
  5773.  
  5774.     if ((!finite) || !(opts.Options & SPLIT_UNION))
  5775.     {
  5776.       if (finite)
  5777.       {
  5778.         Warn(0.0, "CSG union unnecessarily bounded.");
  5779.       }
  5780.  
  5781.       Link(Object, &(Object->Sibling), &(Frame.Objects));
  5782.  
  5783.       return;
  5784.     }
  5785.  
  5786.     Warn(0.0, "Bounded CSG union split.");
  5787.   }
  5788.  
  5789.   /* Link all siblings of a union to the frame. */
  5790.  
  5791.   for (This_Sib = ((CSG *)Object)->Children; This_Sib != NULL; This_Sib = Next_Sib)
  5792.   {
  5793.     /* Link_To_Frame() changes Sibling so save it */
  5794.  
  5795.     Next_Sib = This_Sib->Sibling;
  5796.  
  5797.     /* Sibling is no longer inside a CSG object. */
  5798.  
  5799.     This_Sib->Type &= ~IS_CHILD_OBJECT;
  5800.  
  5801.     Link_To_Frame (This_Sib);
  5802.   }
  5803.  
  5804. /*
  5805.   Object->Texture = NULL;
  5806. */
  5807.  
  5808.   Object->Sibling = NULL;
  5809.  
  5810.   ((CSG *)Object)->Children = NULL;
  5811.  
  5812.   Destroy_Object (Object);
  5813. }
  5814.  
  5815.  
  5816.  
  5817. /*****************************************************************************
  5818. *
  5819. * FUNCTION
  5820. *
  5821. * INPUT
  5822. *
  5823. * OUTPUT
  5824. *
  5825. * RETURNS
  5826. *
  5827. * AUTHOR
  5828. *
  5829. * DESCRIPTION
  5830. *
  5831. * CHANGES
  5832. *
  5833. ******************************************************************************/
  5834.  
  5835. void Only_In(s1,s2)
  5836. char *s1, *s2;
  5837. {
  5838.   Error("Keyword '%s' can only be used in a %s statement.",s1,s2);
  5839. }
  5840.  
  5841.  
  5842.  
  5843. /*****************************************************************************
  5844. *
  5845. * FUNCTION
  5846. *
  5847. * INPUT
  5848. *
  5849. * OUTPUT
  5850. *
  5851. * RETURNS
  5852. *
  5853. * AUTHOR
  5854. *
  5855. * DESCRIPTION
  5856. *
  5857. * CHANGES
  5858. *
  5859. ******************************************************************************/
  5860.  
  5861. void Not_With(s1,s2)
  5862. char *s1, *s2;
  5863. {
  5864.   Error("Keyword '%s' cannot be used %s.",s1,s2);
  5865. }
  5866.  
  5867.